R语言data.table滚动连接:如何基于给定数据表实现匹配?
嘿,我来帮你搞定这个data.table滚动连接的问题!首先咱们明确核心需求:基于id匹配表A和表B,为表A的每一行找到表B中符合日期条件的对应记录——不管是找最近的过去日期,还是最近的未来日期,滚动连接都能轻松实现。
先回顾一下我们的两个数据表(已经帮你把日期转成了Date类型,这是滚动连接的前提,因为需要有序的数值/日期列):
library(data.table) # 定义并初始化数据表 A <- data.table(date = as.Date(c("2003-05-24", "2003-06-05", "2003-06-24", "2003-06-25", "2003-06-27")), id = c(1,2,1,1,2)) B <- data.table(idd = c(1,1,1,1,1), datee = as.Date(c("2003-05-25", "2003-06-06", "2003-06-25", "2003-06-26", "2003-06-28")), value = c(1,2,3,4,5))
表A的内容:
date id1: 2003-05-24 1
2: 2003-06-05 2
3: 2003-06-24 1
4: 2003-06-25 1
5: 2003-06-27 2
表B的内容:
idd datee value
1: 1 2003-05-25 1
2: 1 2003-06-06 2
3: 1 2003-06-25 3
4: 1 2003-06-26 4
5: 1 2003-06-28 5
下面分两种常见场景给出实现方法:
场景1:匹配最近的不晚于A中日期的B记录(过去方向)
我们想为表A的每一行,找到同id且日期小于等于A日期的最大B日期对应的value。可以用roll = TRUE(或roll = Inf)来实现:
方法1:统一列名后设置键连接
# 先把B的列名改成和A匹配的,方便设置键 setnames(B, c("idd", "datee"), c("id", "date")) # 设置键:先按id分组,再按日期排序(滚动连接依赖有序键) setkey(A, id, date) setkey(B, id, date) # 执行滚动连接 result_past <- B[A, roll = TRUE] print(result_past)
结果:
date id value1: 2003-05-24 1 NA # B中id=1的最早日期是2003-05-25,比A的日期晚,无匹配
2: 2003-06-05 2 NA # B中没有id=2的记录,无匹配
3: 2003-06-24 1 2 # B中id=1且<=2003-06-24的最大日期是2003-06-06,对应value=2
4: 2003-06-25 1 3 # 日期完全匹配,直接取value=3
5: 2003-06-27 2 NA # B中无id=2的记录,无匹配
方法2:不修改原表,用on参数指定连接条件
如果不想改动原表的列名,data.table 1.9.6及以上版本支持用on参数直接指定列映射,更灵活:
# 恢复B的原列名(如果之前改了的话) setnames(B, c("id", "date"), c("idd", "datee")) # 设置键(也可以不设置键,直接用on参数,但设置键会更高效) setkey(A, id, date) setkey(B, idd, datee) # 执行滚动连接,指定列映射和滚动方向 result_past2 <- B[A, on = .(idd = id, datee <= date), roll = TRUE]
这个方法得到的结果和上面完全一致。
场景2:匹配最近的不早于A中日期的B记录(未来方向)
如果我们想找同id且日期大于等于A日期的最小B日期对应的value,就用roll = -Inf:
# 用on参数的方式实现(不修改原表) result_future <- B[A, on = .(idd = id, datee >= date), roll = -Inf] print(result_future)
结果:
date id value1: 2003-05-24 1 1 # B中id=1且>=2003-05-24的最小日期是2003-05-25,对应value=1
2: 2003-06-05 2 NA # B中无id=2的记录,无匹配
3: 2003-06-24 1 3 # B中id=1且>=2003-06-24的最小日期是2003-06-25,对应value=3
4: 2003-06-25 1 3 # 日期完全匹配,直接取value=3
5: 2003-06-27 2 NA # B中无id=2的记录,无匹配
关键参数解释
on:用来指定两个表之间的列映射关系,比如.(idd = id, datee >= date)表示用B的idd匹配A的id,同时要求B的datee大于等于A的date。roll:控制滚动连接的方向:TRUE/Inf:向前滚动,匹配最近的小于等于目标值的记录;-Inf:向后滚动,匹配最近的大于等于目标值的记录;- 如果设置为具体数字(比如
roll=7),则只允许滚动该数值范围内的记录(比如7天以内)。
内容的提问来源于stack exchange,提问作者user9621577

