data.table连接时如何指定单列并保留其余表的全部列?
问题
需要将两个data.table(df1和df2)按id=ID,且date_purchase介于start_date和end_date之间进行连接。当前连接代码需手动列出所有列,希望仅指定x.date_purchase,同时可选择保留df1或df2的其余全部列。
示例代码
library(data.table) # 修正原代码中df1 end_date元素数量不匹配的问题 df1 <- data.table( ID = c(1, 2, 3), start_date = as.Date(c("2022-01-01", "2022-10-15", "2022-02-03")), end_date = as.Date(c("2022-01-03", "2022-01-02", "2022-01-01")) ) df2 <- data.table( id = c(1, 1, 7, 8), date_purchase = as.Date(c("2022-01-05", "2022-01-02", "2022-01-01", "2022-01-01")) )
当前手动列列的连接代码
df2[df1,.(x.date_purchase,id,ID,start_date,end_date), on=.(id=ID, date_purchase>=start_date, date_purchase<=end_date), nomatch=0]
预期输出
| ID | start_date | end_date | date_purchase |
|---|---|---|---|
| 1 | 2022-01-01 | 2022-01-03 | 2022-01-02 |
解决方案
利用data.table连接语法中的x.*和i.*快捷方式,可以一键获取对应表的全部列,无需手动逐个列出:
1. 保留df1全部列 + df2的date_purchase
在df2[df1, ...]的结构中,df1是被连接的表(用i指代),df2是主表(用x指代)。通过i.*获取df1的所有列,再指定x.date_purchase,最后可选重命名列以符合预期格式:
result <- df2[df1, .(i.*, x.date_purchase), on = .(id = ID, date_purchase >= start_date, date_purchase <= end_date), nomatch = 0] # 重命名x.date_purchase为date_purchase setnames(result, "x.date_purchase", "date_purchase")
运行后得到的结果与预期一致。
2. 保留df2全部列 + df1的相关列
如果需要保留df2的所有列,同时加入df1的列,用x.*获取df2全部列,再指定i.*或所需的df1列:
result_df2 <- df2[df1, .(x.*, i.start_date, i.end_date), on = .(id = ID, date_purchase >= start_date, date_purchase <= end_date), nomatch = 0]
核心逻辑说明
在data.table的连接表达式X[Y, j, on=...]中:
X对应x,Y对应ix.*表示获取X表的所有列i.*表示获取Y表的所有列- 结合
on参数的范围连接条件,即可实现无需手动列全列的高效连接
内容的提问来源于stack exchange,提问作者GitZine
相关产品推荐
相关产品推荐

