我有两个数据表:
library(data.table)
d1 <- data.table(grp = c("a", "c", "b", "a"), val = c(2, 3, 6, 7), y1 = 1:4, y2 = 5:8)
d2 <- data.table(grp = rep(c("a", "b", "c"), 2),
from = rep(c(1, 5), each = 3), to = rep(c(4, 10), each = 3), z = 11:16)
Run Code Online (Sandbox Code Playgroud)
我执行一个非等联接,其中'd1'中的'val'值应该落在每个组'grp'的'from'和'to'''''定义的范围内.
d1[d2, on = .(grp, val >= from, val <= to), nomatch = 0]
# grp val y1 y2 val.1 z
# 1: a 1 1 5 4 11
# 2: c 1 2 6 4 13
# 3: a 5 4 8 10 14
# 4: b 5 3 7 10 15
Run Code Online (Sandbox Code Playgroud)
在输出中,连接变量来自i('val'和'val.1',其值分别为'from'和'to''在'd2'中).但是,我想改为x加入专栏.现在,因为......
x现在可以使用前缀来引用列,x.并且在连接期间特别有用,可以引用其x连接列,因为它们被is 屏蔽.
......这可以通过指定来实现val = x.val的j:
d1[d2, .(grp, val = x.val, z), on = .(grp, val >= from, val <= to), nomatch = 0]
Run Code Online (Sandbox Code Playgroud)
为了避免键入所有非连接列(可能很多)x中j,我目前的解决办法是加入上面的原始数据,这给期望的结果:
d1[d1[d2, .(grp, val = x.val, z), on = .(grp, val >= from, val <= to), nomatch = 0]
, on = .(grp, val)]
# grp val y1 y2 z
# 1: a 2 1 5 11
# 2: c 3 2 6 13
# 3: a 7 4 8 14
# 4: b 6 3 7 15
Run Code Online (Sandbox Code Playgroud)
然而,这似乎有点笨拙.因此,我的问题:我如何从选择连接列x和所有非连接列x在j一气呵成?
PS我已经考虑切换x和i数据集,并在条件on.虽然这会产生所需的连接值,但它仍然需要后处理(删除,重命名和重新排序列).
PS我考虑过切换x和i数据集,以及打开条件。尽管这会产生所需的联接值,但仍需要后处理(列的删除,重命名和重新排序)。
后处理的数量受到有多少列的限制on=:
d2[d1, on=.(grp, from <= val, to >= val), nomatch=0][,
`:=`(val = from, from = NULL, to = NULL)][]
Run Code Online (Sandbox Code Playgroud)
看起来还不错。
遵循@Jaap的评论,这是另一种方法,通过d1更新联接将列添加到:
nm2 = setdiff(names(d2), c("from","to","grp"))
d1[d2, on=.(grp, val >= from, val <= to), (nm2) := mget(sprintf("i.%s", nm2))]
Run Code Online (Sandbox Code Playgroud)
这在这里很有意义,因为所需的输出本质d1上是加上的某些列d2(因为每行d1匹配项最多匹配的一行d2)。
| 归档时间: |
|
| 查看次数: |
178 次 |
| 最近记录: |