根据 +/- 3 个月内的日期,使用 R 中的 data.table 包连接两个数据框
Join two data frames using the data.table package in R based on dates that are within +/- 3 months
我正在尝试连接两个数据框;通过 ID,使用 R 中的 data.table 包,以及用于日期的 lubridate 包。我只想加入 Date1
之前或之后 3 个月的 Date2 行
df1
ID
Date1
1
2019-09-09
2
2019-09-09
3
2019-09-09
4
2019-09-09
Df2
Id
Date 2
Value
1
2020-09-09
6
1
2019-10-09
7
2
2019-03-13
8
4
2019-10-27
15
我想要的最终数据框
ID
Date1
Id
Date 2
Value
1
2019-09-09
1
2020-09-09
6
2
2019-09-09
2
NA
NA
3
2019-09-09
NA
NA
NA
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)]```
data.table
中的滚动连接非常有用,但掌握起来可能有点困难。 rollends
的语法与你那里的语法有很大不同,它不是为处理任何类型的复杂逻辑而设计的,只是简单的 TRUE
/FALSE
案例。
无论如何,这是解决此问题的一种方法。使用月份算术作为过滤条件并结合 nearest
值要求使这是一个多步问题而不是一步连接 (至少我能看到的任何方式).
虽然 join/filter/copy 结果值操作在技术上是单行的,但我尽力添加了大量对嵌套操作的解释。
## 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
这是我用于滚动连接的三个首选资源(包文档除外),它们都帮助我了解了多年来在多个方面的一些怪癖。
我正在尝试连接两个数据框;通过 ID,使用 R 中的 data.table 包,以及用于日期的 lubridate 包。我只想加入 Date1
之前或之后 3 个月的 Date2 行df1
ID | Date1 |
---|---|
1 | 2019-09-09 |
2 | 2019-09-09 |
3 | 2019-09-09 |
4 | 2019-09-09 |
Df2
Id | Date 2 | Value |
---|---|---|
1 | 2020-09-09 | 6 |
1 | 2019-10-09 | 7 |
2 | 2019-03-13 | 8 |
4 | 2019-10-27 | 15 |
我想要的最终数据框
ID | Date1 | Id | Date 2 | Value |
---|---|---|---|---|
1 | 2019-09-09 | 1 | 2020-09-09 | 6 |
2 | 2019-09-09 | 2 | NA | NA |
3 | 2019-09-09 | NA | NA | NA |
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)]```
data.table
中的滚动连接非常有用,但掌握起来可能有点困难。 rollends
的语法与你那里的语法有很大不同,它不是为处理任何类型的复杂逻辑而设计的,只是简单的 TRUE
/FALSE
案例。
无论如何,这是解决此问题的一种方法。使用月份算术作为过滤条件并结合 nearest
值要求使这是一个多步问题而不是一步连接 (至少我能看到的任何方式).
虽然 join/filter/copy 结果值操作在技术上是单行的,但我尽力添加了大量对嵌套操作的解释。
## 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
这是我用于滚动连接的三个首选资源(包文档除外),它们都帮助我了解了多年来在多个方面的一些怪癖。