如何高效关联data.table并保留原列?含不等式关联条件
高效实现data.table多条件关联(保留原字段)
问题背景
现有两个data.table数据结构:
library(data.table) d = seq(0.1,1,by = 0.1) n = length(d) dtBig = data.table(id = rep(letters[1:2],each = n/2), d1 = d, d2 = d + 0.2, i = 1:n) dtSmall = data.table(id = rep(letters[1:2],each = 2), d_start = c(0.2,0.65,0.15,1.1), d_end = c(0.65,0.85,0.8,1.5))
需求是基于id字段进行关联,同时满足两个不等式筛选条件:d1 >= d_start和d2 <= d_end。
低效的初始方法
直接使用merge加行过滤的方式,在数据量较大时性能极差:
dtAll = merge(dtSmall, dtBig, by = "id", allow.cartesian = T)[d1 >= d_start & d2 <= d_end]
on操作符的使用问题
尝试用data.table的on操作符做条件连接,虽然效率提升,但会覆盖dtBig中原有的d1和d2值:
dtAll2 = dtBig[dtSmall, on = .(id, d1 >= d_start, d2 <= d_end),nomatch = 0]
后续通过两次连接恢复原字段的方式步骤繁琐:
dtAll2 = dtBig[dtSmall, on = .(id, d1 >= d_start, d2 <= d_end),nomatch = 0] dtAll2[,`:=`(d_start = d1, d_end = d2)] dtAll2[,`:=`(d1 = NULL, d2 = NULL)] dtAll2 = dtAll2[dtBig[,.(i,d1,d2)],on = .(i == i),nomatch = 0]
更优实现思路
在条件连接时,直接通过x.前缀引用dtBig的原始字段,同时指定输出列,一步到位得到目标结果,无需后续恢复操作:
dtAllOpt = dtBig[dtSmall, on = .(id, d1 >= d_start, d2 <= d_end), nomatch = 0, .(id, i, d1 = x.d1, d2 = x.d2, d_start, d_end)]
这里的x.d1和x.d2明确指向dtBig中的原始d1、d2字段,连接条件仅用于筛选匹配行,不会覆盖原字段值。
结果一致性验证
用以下代码验证优化后结果与原方法结果一致:
setcolorder(dtAll, names(dtAllOpt)) setkey(dtAll, i) setkey(dtAllOpt, i) all.equal(dtAll, dtAllOpt)
内容的提问来源于stack exchange,提问作者Lolivano
相关产品推荐
相关产品推荐

