使用`j`选择`x`的连接列及其所有非连接列

Hen*_*rik 9 r data.table

我有两个数据表:

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.valj:

d1[d2, .(grp, val = x.val, z), on = .(grp, val >= from, val <= to), nomatch = 0]
Run Code Online (Sandbox Code Playgroud)

为了避免键入所有非连接列(可能很多)xj,我目前的解决办法是加入上面的原始数据,这给期望的结果:

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和所有非连接列xj一气呵成?


PS我已经考虑切换xi数据集,并在条件on.虽然这会产生所需的连接值,但它仍然需要后处理(删除,重命名和重新排序列).

Fra*_*ank 5

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)。