data.table 有条件连接:保留所有列

2024-01-10

我有这两张表

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 and d2 <= d_end.

当表有很多行时,第一种方法非常耗时:

dtAll = merge(dtSmall, dtBig, by = "id", allow.cartesian = T)[d1 >= d_start & d2 <= d_end]

所以我使用“on”运算符:

dtAll2 = dtBig[dtSmall, on = .(id, d1 >= d_start, d2 <= d_end),nomatch = 0]

但是,d1 采用 d_start 的值和 d_end 的 d2 的值,并且我丢失了 d1 和 d2 的值。
所以我做了这些命令:

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]

验证 dtAll 和 dtAll2 是否相同:

setcolorder(dtAll, names(dtAll2))
setkey(dtAll,i)
setkey(dtAll2,i)
all.equal(dtAll,dtAll2)

但我确信有更好的方法,有什么想法吗?


您可以使用foverlaps可用的data.table为此,并从您的d1 >= d_start & d2 <= d_end我们可以看出您对 dtBig 中的那些记录感兴趣withindtSmall 中开始/结束的范围,可以在type争论。你必须使用setkey on the y(第二个表,dtSmall)。你不必使用by.y因为它默认为 y 中的键。

setkey(dtSmall, id, d_start, d_end)
dtAllF <- foverlaps(dtBig, dtSmall, by.x = c("id", "d1", "d2"), type = "within", nomatch = 0)

Results

dtAllF
# id d_start d_end  d1  d2 i
# 1:  a    0.20  0.65 0.2 0.4 2
# 2:  a    0.20  0.65 0.3 0.5 3
# 3:  a    0.20  0.65 0.4 0.6 4
# 4:  b    0.15  0.80 0.6 0.8 6

检查是否相等

setcolorder(dtAllF, c("id", "i"))
identical(dtAll2, dtAllF)

# [1] TRUE
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

data.table 有条件连接:保留所有列 的相关文章

随机推荐