【问题标题】:Matching values by nearest POSIXct in two data frames keeping both dates在两个数据框中按最近的 POSIXct 匹配值,同时保持两个日期
【发布时间】:2020-02-24 19:30:59
【问题描述】:

我有两个要按最近日期匹配的数据框,创建一个新数据框,其中包含两者的值(包括“最近日期匹配”)。正是关于包括最近日期匹配的最后一部分给我带来了问题。

#Data sets

date1= as.POSIXct(c("2013-08-03", "2013-09-04", "2013-09-08", "2013-09-12", "2013-11-01"))
date2= as.POSIXct(c("2013-08-06", "2013-09-20", "2013-09-12", "2013-09-14", "2014-11-01","2010-11-01","2014-06-01"))

Num1<-seq(1,5)
Num2<-seq(1,7)


DF1<-data.frame(date1,Num1)
DF2<-data.frame(date2,Num2)

这个 for 循环给了我我想要的东西,但是在我的数据集上运行的时间太长了。

for(i in seq(1,nrow(DF1))){


  Data<-DF1[i,]

  #Date
  DataDate<-Data$date1

  MinTime<-which.min(abs(DataDate-DF2$date2))
  Data2<-DF2[MinTime,]
  DF1[i,'NearestNum2']<-Data2[,"Num2"]
  DF1[i,'NearestDate2']<-Data2[,"date2"]
  DF1[i,'TimeDiff']<-as.numeric(difftime(DF1[i,'date1'], DF1[i,'NearestDate2'], units='secs'))

}

DF1

我使用 data.table 包找到了一些类似问题的优秀答案。根据之前的答案,这就是我厌倦的:

#This line should provide with me with the numerical value associated with the nearest date
    setDT(DF1)[, NearestNum2 := setDT(DF2)[DF1, Num2, on=c(date2="date1"), roll="nearest"]]

#This line "should provide me with the actual nearest date used, but does not
    setDT(DF1)[, NearestDate1 := setDT(DF2)[DF1, date2, on=c(date2="date1"), roll="nearest"]]

这里的问题是(与 for 循环结果相反),使用 data.table 代码的“nearestDate2”列只是原始日期的重复。有人可以提供一个 data.table (或任何有效的代码),可以为我提供与上述 for 循环相同的输出吗?

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    不确定为什么您的原始解决方案不起作用,但这里有一个替代设置可以完成这项工作:

    setDT(DF1)
    setDT(DF2)
    
    DF1[, c("NearestNum2", "NearestDate2") := 
            DF2[.SD, on = .(date2 = date1), .(x.Num2, x.date2), roll = "nearest"]
        ][,  TimeDiff := as.numeric(difftime(date1, NearestDate2))]
    
    DF1
    
            date1 Num1 NearestNum2 NearestDate2 TimeDiff
    1: 2013-08-03    1           1   2013-08-06  -259200
    2: 2013-09-04    2           3   2013-09-12  -691200
    3: 2013-09-08    3           3   2013-09-12  -345600
    4: 2013-09-12    4           3   2013-09-12        0
    5: 2013-11-01    5           2   2013-09-20  3628800
    

    【讨论】:

    • 不错的答案!它也可以在没有 .SD 的情况下在 DF2 中工作。
    • @DirkEddelbuettel 谢谢!我不知道!我猜i 在另一个 data.table 中调用 data.table 时默认为 .SD?
    【解决方案2】:

    这里有一些方法可以按日期将 DF1 中的每一行与 DF2 中最近的行进行匹配。

    1) sqldf

    library(sqldf)
    sqldf("select *, min(abs(date2 - date1)) AbsDiff, date2 - date1 TimeDiff
           from DF1 a join DF2 b group by a.rowid")
    

    给予:

           date1 Num1      date2 Num2 AbsDiff TimeDiff
    1 2013-08-03    1 2013-08-06    1  259200   259200
    2 2013-09-04    2 2013-09-12    3  691200   691200
    3 2013-09-08    3 2013-09-12    3  345600   345600
    4 2013-09-12    4 2013-09-12    3       0        0
    5 2013-11-01    5 2013-09-20    2 3628800 -3628800
    

    2) 基础R

    abs.min <- function(d1) which.min(abs(d1 - DF2$date2))
    transform(cbind(DF1, DF2[sapply(DF1$date1, abs.min), ]), 
              TimeDiff = as.numeric(date2 - date1))
    

    给予:

             date1 Num1      date2 Num2 TimeDiff
    1   2013-08-03    1 2013-08-06    1   259200
    3   2013-09-04    2 2013-09-12    3   691200
    3.1 2013-09-08    3 2013-09-12    3   345600
    3.2 2013-09-12    4 2013-09-12    3        0
    2   2013-11-01    5 2013-09-20    2 -3628800
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-20
      • 2022-06-28
      相关资源
      最近更新 更多