我确定我忽略了显而易见的内容,但是我找不到一种方法可以一步一步地将data.table
非查找联接中的“ lookup”表的所有列联接在一起。
我看了Arun的演示文稿(https://github.com/Rdatatable/data.table/wiki/talks/ArunSrinivasanSatRdaysBudapest2016.pdf)和多个SO问题,但几乎所有问题都只涉及更新单个列,而不涉及多个列。
假设我有2个data.tables a
和b
:
library(data.table) a <- data.table(Company_ID = c(1,1,1,1), salary = c(2000, 3000, 4000, 5000)) # Company_ID salary # 1: 1 2000 # 2: 1 3000 # 3: 1 4000 # 4: 1 5000 b <- data.table(cat = c(1,2), LB = c(0, 3000), UB = c(3000,5000), rep = c("Bob","Alice")) # cat LB UB rep # 1: 1 0 3000 Bob # 2: 2 3000 5000 Alice
我最终想要的是将cat,LB,UB,rep(在中的所有cols b
)与表进行匹配a
:
# Company_ID salary cat LB UB rep # 1: 1 2000 1 0 3000 Bob # 2: 1 3000 2 3000 5000 Alice # 3: 1 4000 2 3000 5000 Alice
当前,我设法做到这一点的唯一方法是使用以下两行:
a <- a[b, on = .(salary >= LB, salary < UB), cat := cat] a[b, on = .(cat == cat)]
它输出所需的表,但看起来很麻烦,根本不像一种data.table
方法。任何帮助将不胜感激!
由于您希望每一行都有结果a
,因此您应该像这样进行联接b[a, ...]
:
b[a, on=.(LB <= salary, UB > salary), nomatch=0, .(Company_ID, salary, cat, LB = x.LB, UB = x.UB, rep)] Company_ID salary cat LB UB rep 1: 1 2000 1 0 3000 Bob 2: 1 3000 2 3000 5000 Alice 3: 1 4000 2 3000 5000 Alice
nomatch=0
表示我们将删除a
中不匹配的行b
。
我们需要使用前缀(来自docs,其中的参数命名为)来显式地引用UB
和LB
列。b
x.*
?data.table
x[i]
关于奇怪的默认cols,有一个开放的问题可以更改该行为:#1615。
(现在已修复以下的第1989年版本,请参见Uwe的答案。)
或者...一种可行的方法,可以避免显式列出所有列:将a
的列添加到b
,然后添加子集b
:
b[a, on=.(LB <= salary, UB > salary), names(a) := mget(paste0("i.", names(a)))] b[b[a, on=.(LB <= salary, UB > salary), which=TRUE, nomatch=0]]
这有两个问题。首先,有一个错误会导致非等额联接在遇到mget
(#1989)时中断。临时的解决方法是枚举a
的列:
b[a, on=.(LB <= salary, UB > salary), `:=`(Company_ID = i.Company_ID, salary = i.salary)] b[b[a, on=.(LB <= salary, UB > salary), which=TRUE, nomatch=0]]
其次,两次执行此联接效率不高(一次为:=
,第二次为which
),但是我看不到任何解决方法……也许证明允许同时允许j
和which
?