代码之家  ›  专栏  ›  技术社区  ›  Denis

如何找到距离给定日期最近的日期?

  •  0
  • Denis  · 技术社区  · 6 年前

    dates.zoo <- zoo(data.frame(val=seq(1:121)), order.by = seq.Date(as.Date('2018-12-01'), as.Date('2019-03-31'), "days"))
    monthly.zoo <- zoo(data.frame(val=c(1,2,4)), order.by = c(as.Date('2018-12-14'), as.Date('2019-1-2'), as.Date('2019-2-3')))
    

    对于中的每个日期 dates.zoo 我想将其与中最近的前一个日期对齐 monthly.zoo NA 如果没有找到每月日期)。数据也是如此。我期望的帧/动物园对象是:

    ...
    2018-12-02   2  NA
    ...
    2018-12-14  14  2018-12-14
    2018-12-15  15  2018-12-14
    2018-12-16  16  2018-12-14
    ...
    2019-01-01  32  2018-12-14
    2019-01-02  33  2019-01-02
    2019-01-03  34  2019-01-02
    ...
    

    0 回复  |  直到 6 年前
        1
  •  4
  •   John    2 年前

    findInterval .我们可以做到:

    library(zoo)
    interval.idx <- findInterval(index(dates.zoo), index(monthly.zoo))
    interval.idx <- ifelse(interval.idx == 0, NA, interval.idx)
    dates.zoo$month <- index(monthly.zoo)[interval.idx]
    
        2
  •  3
  •   Community CDub    4 年前

    使用数据的滚动连接。可以使用表。 https://www.r-bloggers.com/understanding-data-table-rolling-joins/

    也是一种使用base-R的解决方案

    数据表格解决方案

    library(data.table)
    dates.df <- data.table(val=seq(1:121), dates = seq.Date(as.Date('2018-12-01'), as.Date('2019-03-31'), "days"))
    monthly.df <- data.table(val=c(1,2,4,5), dates = c(as.Date('2018-12-14'), as.Date('2019-1-2'), as.Date('2019-2-3')))
    
    setkeyv(dates.df,"dates")
    setkeyv(monthly.df,"dates")
    
    #monthly.df[,nearest:=(dates)][dates.df,roll = 'nearest'] #closest date
    monthly.df[,nearest:=(dates)][dates.df,roll = Inf] #Closest _previous_ date
    

    dates.df <- zoo(data.frame(val=seq(1:121)), order.by = seq.Date(as.Date('2018-12-01'), as.Date('2019-03-31'), "days"))
    monthly.df <- zoo(data.frame(val=c(1,2,4)), order.by = c(as.Date('2018-12-14'), as.Date('2019-1-2'), as.Date('2019-2-3')))
    
    dates.df <- data.frame(val=dates.df$val,dates=attributes(dates.df)$index)
    monthly.df <- data.frame(val=monthly.df$val,dates=attributes(monthly.df)$index)
    
    min_distances <- as.numeric(dates.df$dates)- matrix(rep(as.numeric(monthly.df$dates),nrow(dates.df)),ncol=length(monthly.df$dates),byrow=T)
    min_distances <- as.data.frame(t(min_distances))
    
    closest <- sapply(min_distances,function(x) 
      { 
        w <- which(x==min(x[x>0])); 
        ifelse(length(w)==0,NA,w) 
      })
    
    dates.df$closest_month <- monthly.df$dates[closest]
    

    结果:data.table

    > monthly.df[,nearest:=(dates)][dates.df,roll = Inf]
         val      dates    nearest i.val
      1:  NA 2018-12-01       <NA>     1
      2:  NA 2018-12-02       <NA>     2
      3:  NA 2018-12-03       <NA>     3
      4:  NA 2018-12-04       <NA>     4
      5:  NA 2018-12-05       <NA>     5
     ---                                
    118:   4 2019-03-27 2019-02-03   117
    119:   4 2019-03-28 2019-02-03   118
    120:   4 2019-03-29 2019-02-03   119
    121:   4 2019-03-30 2019-02-03   120
    122:   4 2019-03-31 2019-02-03   121
    

    > dates.df[64:69,]
               val      dates closest_month
    2019-02-02  64 2019-02-02    2019-01-02
    2019-02-03  65 2019-02-03    2019-01-02
    2019-02-04  66 2019-02-04    2019-02-03
    2019-02-05  67 2019-02-05    2019-02-03
    2019-02-06  68 2019-02-06    2019-02-03
    2019-02-07  69 2019-02-07    2019-02-03
    
        3
  •  1
  •   IceCreamToucan    6 年前

    dates.df ,您希望在中获取最近的日期 monthly.df 是按日期升序排序的,您可以使用以下方法。它统计中的行数 每月.df 指数小于给定日期,这相当于以下情况下的指数: mothly.df 按日期升序排序。如果此类行为0,则索引将更改为 NA .

    inds <- rowSums(outer(index(dates.df), index(monthly.df), `>`))
    inds[inds == 0] <- NA
    dates.df_monthmatch <- index(monthly.df)[inds]
    
    
    dates.df_monthmatch
    #   [1] NA           NA           NA           NA           NA           NA          
    #   [7] NA           NA           NA           NA           NA           NA          
    #  [13] NA           NA           "2018-12-14" "2018-12-14" "2018-12-14" "2018-12-14"
    #  [19] "2018-12-14" "2018-12-14" "2018-12-14" "2018-12-14" "2018-12-14" "2018-12-14"
    #  [25] "2018-12-14" "2018-12-14" "2018-12-14" "2018-12-14" "2018-12-14" "2018-12-14"
    #  [31] "2018-12-14" "2018-12-14" "2018-12-14" "2019-01-02" "2019-01-02" "2019-01-02"
    #  [37] "2019-01-02" "2019-01-02" "2019-01-02" "2019-01-02" "2019-01-02" "2019-01-02"
    #  [43] "2019-01-02" "2019-01-02" "2019-01-02" "2019-01-02" "2019-01-02" "2019-01-02"
    #  [49] "2019-01-02" "2019-01-02" "2019-01-02" "2019-01-02" "2019-01-02" "2019-01-02"
    #  [55] "2019-01-02" "2019-01-02" "2019-01-02" "2019-01-02" "2019-01-02" "2019-01-02"
    #  [61] "2019-01-02" "2019-01-02" "2019-01-02" "2019-01-02" "2019-01-02" "2019-02-03"
    #  [67] "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03"
    #  [73] "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03"
    #  [79] "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03"
    #  [85] "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03"
    #  [91] "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03"
    #  [97] "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03"
    # [103] "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03"
    # [109] "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03"
    # [115] "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03" "2019-02-03"
    # [121] "2019-02-03"
    
        4
  •  0
  •   Chabo    6 年前

    这是一种可能性,尽管我必须将对象更改为数据帧才能指定动物园索引日期。该代码将月份、年份和最后一天与小于或等于要匹配日期的条件进行比较。如果没有符合此标准的日期,则分配NA。这些比较是通过包“lubridate”检查单个日期元素,然后逻辑索引最佳匹配来完成的。

    library(zoo)
    library(lubridate)
    
    dates.df <- zoo(data.frame(val=seq(1:121)), order.by = seq.Date(as.Date('2018-12-01'), as.Date('2019-03-31'), "days"))
    monthly.df <- zoo(data.frame(val=c(1,2,4)), order.by = c(as.Date('2018-12-14'), as.Date('2019-1-2'), as.Date('2019-2-3')))
    
    month_m<-month(monthly.df)
    month_d<-month(dates.df)
    
    year_m<-year(monthly.df)
    year_d<-year(dates.df)
    
    day_m<-day(monthly.df)
    day_d<-day(dates.df)
    
    index<-list()
    Index<-list()
    
    for( i in 1:length(monthly.df)){
    
    index[[i]]<-which(month_m[i] == month_d & year_m[i] == year_d
                      & day_d <= day_m[i])
    
    test<-unlist(index[[i]])
    
       #Assigns NA if no suitable match is found
       if(length(test)==0){
        print("NA")
        Index[[i]]=NA
        }else {
        Index[[i]]<-tail(test, n=1)
        }                      
    }
    
    Test<-unlist(Index)
    monthly.df_Fin<-as.data.frame(monthly.df)
    dates.df_Fin<-as.data.frame(dates.df)
    monthly.df_Fin$match<-as.character(row.names(dates.df_Fin)[Test])
    monthly.df_Fin$value<-dates.df_Fin[Test,]
    
    > monthly.df_Fin
               val      match value
    2018-12-14   1 2018-12-14    14
    2019-01-02   2 2019-01-02    33
    2019-02-03   4 2019-02-03    65
    

    假设我们更改了一个超出critera范围的值:

    monthly.df <- zoo(data.frame(val=c(1,2,4)), order.by = c(as.Date('2018-12- 
    14'), as.Date('2019-1-2'), as.Date('2017-2-3')))
    
    ....
    
    #Result
    > monthly.df_Fin
               val      match value
    2017-02-03   4       <NA>    NA
    2018-12-14   1 2018-12-14    14
    2019-01-02   2 2019-01-02    33