【问题标题】:How can I return the date on which a criteria was fulfilled from a list in R?如何从 R 中的列表返回满足条件的日期?
【发布时间】:2021-06-08 21:28:58
【问题描述】:

我想为列表中的每一年数据(长达 30 年)定位每日温度低于 0 度的第一个和最后一个日期,并返回事件发生的儒略日(Day Of Year)对于网格中的每个单元格。

这是我的示例数据集: 我的列表中有 30 年的每日最低温度数据:

#First create the example dataset of dimensions: Days,Lat,Lon

tmin=array(-2:35, c(10958,11,10))

#create the list

Variable <- list(varName="tmin")
Data = tmin
xyCoords <- list(x = seq(-4.37,1.37,length.out=10), y = seq(45.37,52.37,length.out=11))
Dates <- list(start = seq(as.Date("1976-01-01"), as.Date("2005-12-31"), by="days"), end=seq(as.Date("1976-01-01"), as.Date("2005-12-31"), by="days"))
All <- list(Variable = Variable,Data=Data, xyCoords=xyCoords,Dates=Dates)
#Make sure the dates are characters (as in the original dataset I'm, working with)
All$Dates$start=as.character(All$Dates$start)
All$Dates$end=as.character(All$Dates$end)

我希望按年份对数据进行子集化(例如,第 1 年的数据将是 1:365x11x10)以评估该年每一天的 11X10 网格中的每个单元格是否小于零。发生这种情况的第一个实例是“第一次霜冻的日期”,我想保存发生这种情况的日期。最终,我会在第一个发生日期得到大小为 30x11x10 的数据,第一年看起来像这样(当温度第一次降至零以下时,DOY 的 11 x 10 矩阵):

我还想为最后一次低于零的温度创建另一个 30x11x10 日期输出。

首先,我创造了我的儒略时代/DOY:

#Convert the dates into julian days
require(lubridate)
tmp<-as.Date(All$Dates$start)
doy  <-  yday(tmp)

并提取年份:

yr  <-  year(tmp)
unique.yrs<-unique(yr)

我在这之后的想法是循环匹配所有 unique.yrs[i] 实例的日期。

for (i in 1:length(yr)){
  #Find the indices for the data by identifying the year
yridx<-which(yr ==unique.yrs[i], arr.ind = TRUE)
  #Get the year of data using the year indices
yr.data<-All$Data[yridx,,]
#Identify where temperatures<0 occurred
frost<-which(yr.data <0, arr.ind = TRUE)
}

此时,我返回了每次出现低于零的 3d 索引:

我不知道从这里去哪里。我想如果我能得到每年网格中每个单元格的所有霜冻发生情况,那么也许我可以使用head 来获取第一个实例并使用tail 来获取最后一个实例?所以也许我应该在一个循环中再次设置子集?

我意识到我在这里没有提供完整的代码集,但对 R 来说相对较新,我需要知道我是否以错误的方式处理这一切。我提议的前进路线是否过于复杂?有没有更好的办法?

############################################## ################################################# ################################################# ####### #这是我想出的……它并不优雅,但我认为它有效:

firstoccur=array(numeric(),c(30,11,10))
lastoccur=array(numeric(),c(30,11,10))
yrcntr<-0
for (j in unique.yrs) {
  indcntr<-0
  yrcntr<-yrcntr+1
  ind=which(yr==j)

  for (i in ind) {
    indcntr<-indcntr+1
    for (ii in 1:11){
      for (jj in 1:10){
        if (Data[i,ii,jj]<0 && is.na(firstoccur[yrcntr,ii,jj])){
          firstoccur[yrcntr,ii,jj]<-doy[ind[indcntr]]
        }
      }
    }
  }
}

【问题讨论】:

    标签: r arrays list date


    【解决方案1】:

    此过程创建两个列表,my_list_firstmy_list_last。 My_list_first 是一个长度为 30 的列表,其标识符从 1976 年到 2005 年的每一年。每个条目的第一个条目是温度第一次降至 0 以下的确切日期,第二个条目是与之关联的 11x10 网格日。例如,

     my_list_first[[1]][[1]]
     "1976-01-01"
     my_list_first[[30]][[1]]
     "2005-01-01"
     my_list_last[["2000"]][[2]]
          [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
     [1,]    9   11   13   15   17   19   21   23   25    27
     [2,]   23   25   27   29   31   33   35   -1    1     3
     [3,]   -1    1    3    5    7    9   11   13   15    17
     [4,]   13   15   17   19   21   23   25   27   29    31
     [5,]   27   29   31   33   35   -1    1    3    5     7
     [6,]    3    5    7    9   11   13   15   17   19    21
     [7,]   17   19   21   23   25   27   29   31   33    35
     [8,]   31   33   35   -1    1    3    5    7    9    11
     [9,]    7    9   11   13   15   17   19   21   23    25
     [10,]   21   23   25   27   29   31   33   35   -1     1
     [11,]   35   -1    1    3    5    7    9   11   13    15
    

    代码的操作是从每年的第一天开始向前查找第一次出现零以下温度的日期,然后从每年的最后一天向后查找零温度以下的最后一天。它将这些信息存储在名为 my_list_first 和 my_list_last 的列表中。每个键都是年份,每个条目都有两个组成部分,确切的日期和温度的纬度/经度网格。

    my_list_first=list()
    my_list_last=list()
    for (j in unique.yrs) {
      ind=which(yr==j)
      firstoccur=numeric()
      lastoccur=numeric()
      for (i in ind) {
        if (any(tmin[i,,]<0)) {
          firstoccur=i
          break
        }
      }
      for (i in rev(ind)) {
        if (any(tmin[i,,]<0)) {
          lastoccur=i
          break
        }
      }
      my_list_first[[toString(j)]]=list(All$Dates$start[firstoccur], tmin[firstoccur,,])
      my_list_last[[toString(j)]]=list(All$Dates$start[lastoccur], tmin[lastoccur,,])
    }
    

    【讨论】:

    • 我喜欢你用这个去哪里,但恐怕它不能给我我需要的东西。我需要 11x10 矩阵中每个单元格的发生日期。例如,在上面的my_list_last 中,我需要在每个 i,j 索引中添加一个日期(在 DOY 中):my_list_last[["2000"]][[2]][i,j] 而不是纬度?
    • 不确定我是否理解,11x10 网格中有哪些日期?每年不是只有一个日期第一次和最后一次温度低于 0 度吗?
    • 是的,完全正确。但是对于 11x10 网格中的每个 i,j 单元格,该日期可能不同(因为每个单元格都是不同的位置。我实际上是通过循环计算出来的(添加到上面的问题中)。感谢您的帮助。您将我设置在正确的方向。
    • 顺便说一下,如果你想要一个替代方案,这会得到相同的结果。我使用identical 函数检查了您的结果和来自此的结果。 year=1 for (j in unique.yrs) { ind=which(yr==j) for (i in 1:11) { for (k in 1:10) { firstoccur[year,i,k]=which(tmin[ind,i,k]&lt;0)[1] lastoccur[year,i,k]=which(tmin[rev(ind),i,k]&lt;0)[1] } } year=year+1 }
    • 成功了一半!对于firstoccur,您的解决方案要整洁得多,但对于lastoccur,您不能将ind 直接用作索引(因为它是相反的)。这在下面通过减去 ind 的长度并加 1 得到索引来解决。 lastoccur=array(numeric(),c(30,11,10)) year=1 for (j in unique.yrs) { ind=which(yr==j) for (i in 1:11) { for (k in 1:10) { lastoccur[year,i,k]=(length(ind)+ 1) - which(tmin[rev(ind),i,k]&lt;0)[1] } } year=year+1 }感谢您的帮助!非常感谢。
    猜你喜欢
    • 2021-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-29
    • 2019-04-30
    • 2018-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多