首页 > 解决方案 > 根据 +/- 3 个月内的日期,使用 R 中的 data.table 包连接两个数据框

问题描述

我正在尝试加入两个数据框;按 ID,使用 R 中的 data.table 包,以及日期的 lubridate 包。我只想加入在 Date1 之前或之后 3 个月的 Date2 行

df1

ID 日期1
1 2019-09-09
2 2019-09-09
3 2019-09-09
4 2019-09-09

Df2

ID 日期 2 价值
1 2020-09-09 6
1 2019-10-09 7
2 2019-03-13 8
4 2019-10-27 15

我想要的最终数据框

ID 日期1 ID 日期 2 价值
1 2019-09-09 1 2020-09-09 6
2 2019-09-09 2 不适用 不适用
3 2019-09-09 不适用 不适用 不适用
4 2019-09-09 4 2019-10-27 15

我在下面包含了我的代码。我收到错误说不需要滚动后的 =,但我认为它是必需的。

library(data.table)
library(lubridate)

df1 <- data.table(ID = seq_len(4L),
                  Date1 = as.Date("2019-09-09"))

df2 <- data.table(Id = c(1L, 1L, 2L, 4L),
                  Date2 = as.Date(c("2020-09-09","2019-10-09","2019-03-13","2019-10-27")),
                  Value = c(6L, 7L, 8L, 15L))


df2[, Date1Copy := Date2]  
df2[, IDcopy := Id] 
setkey(df2, ID, Date2)    ## set the column to perform the join on
setkey(df, ID, Date1) 
test = df1[df2, rollends = if (roll=="nearest") c(TRUE,TRUE)
           else if (roll = as.Date(Date1)%m+% months(3)|roll = as.Date(Date1)%m-% months(3)) c(FALSE,TRUE)
           else c(TRUE,FALSE)]```

标签: rjoindata.tablelubridate

解决方案


滚动连接data.table非常有用,但可能有点难以掌握。for 的语法与rollends您那里的语法有很大不同,它不是为处理任何类型的复杂逻辑而设计的,只是简单的TRUE/FALSE案例。

无论如何,这是解决这个问题的一种方法。使用月份算术作为过滤标准并结合nearest值要求使得这是一个多步问题,而不是一步连接(至少我能看到的任何方式)

虽然连接/过滤/复制结果值操作在技术上是单行的,但我尽我所能添加了大量对嵌套操作的解释。

## Make a copy of Date2 to use as key, as it will be inaccessible within the joined table
df2[, Date2Copy := Date2]

## Set Keys
setkey(df1,ID,Date1)
setkey(df2,Id,Date2Copy)

## Step 3: (read the inner nested steps first!)
## After performing the steps 1/2, join the intermediate result table back to `df1`...
df1[
  ## Step 1:
  ## First use the key of `df1` to subset `df2`` with a rolling join
  df2[df1,.(ID, Date1, Date2), roll = "nearest"
      ## Step 2:
      ## Then apply the +/- 3 month filtering critera
      ][between(Date2,
                Date1 %m-% months(3),
                Date1 %m+% months(3))]
  ## Step 3:
  ## ...on the `ID` column and add the intermediate results
  ## for `Date2` and `Value` columns to `df1` by reference
  , c("Date2","Value") := .(i.Date2,i.Value), on = .(ID)]
     
## Results    
print(df1)
#    ID      Date1      Date2 Value
# 1:  1 2019-09-09 2019-10-09     7
# 2:  2 2019-09-09       <NA>    NA
# 3:  3 2019-09-09       <NA>    NA
# 4:  4 2019-09-09 2019-10-27    15

这些是我用于滚动连接的三个首选资源(包文档除外),它们都帮助我理解了多年来在多个点上的一些怪癖。


推荐阅读