r - 根据 +/- 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)]```
解决方案
滚动连接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
这些是我用于滚动连接的三个首选资源(包文档除外),它们都帮助我理解了多年来在多个点上的一些怪癖。
推荐阅读
- python-3.x - Python 3.+ 中的 CVXPY 1.0.24 无法正确解决四边形问题
- kubernetes - 无法使用 Azure Devops Pipeline Kubernetes@1 任务运行多个 kubectl 命令
- ios - 禁用 UIStackView 中特定堆栈的滚动
- docker - 如何在 docker 映像中应用 nix-shell 配置?
- python - 如何将具有相同列名的列数据的多个工作表复制并粘贴到另一个excel文件
- swift - 从 Contacts Framework 获取联系人在 iOS 13 中不起作用
- reactjs - 反应:子路由导致空白全屏,而不是出现在
- excel - 如何使用 VBA 激活表格的排序功能?
- php - 使用 PHP Simple HTML DOM 从“data-srcset”属性中仅获取一个 URL
- r - 与 data.table 合并/加入与合并功能不同