我确定我忽视了显而易见的事情,但我无法找到一种方法来加入"查找"的所有列。只需一步即可data.table
非等同加入的表。
我查看了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(b
中的所有cols)到表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
方法。任何帮助将不胜感激!
答案 0 :(得分:2)
由于您希望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
行。 UB
前缀明确引用LB
中的b
和x.*
列(来自?data.table
文档,其中参数命名为x[i]
)。关于奇怪的默认cols,有一个未解决的问题可以改变这种行为:#1615。
替代...... 应采用的一种方法,避免明确列出所有列:将a
的列添加到b
,然后将子集{{1 }}:
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]]
(#1989)时,会出现导致非等联接中断的错误。临时解决方法是枚举mget
列:
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
?
答案 1 :(得分:2)
现在,#1989已使用data.table版本1.12.3(正在开发中)修复,可以从a
和b
中选择所有列,而无需说明每个列的名称明确地:
a[b, on = .(salary >= LB, salary < UB),
mget(c(paste0("x.", names(a)), paste0("i.", names(b))))]
x.Company_ID x.salary i.cat i.LB i.UB i.rep 1: 1 2000 1 0 3000 Bob 2: 1 3000 2 3000 5000 Alice 3: 1 4000 2 3000 5000 Alice
返回OP的预期结果,但列标题除外。
要更改列标题,可以使用setnames()
包中的data.table
:
result <- a[b, on = .(salary >= LB, salary < UB),
mget(c(paste0("x.", names(a)), paste0("i.", names(b))))]
setnames(result, c(names(a), names(b)))
result
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
或者,通过配管并使用set_names()
包中的magrittr
library(magrittr)
a[b, on = .(salary >= LB, salary < UB),
mget(c(paste0("x.", names(a)), paste0("i.", names(b)))) %>%
set_names(c(names(a), names(b)))]
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
诚然,这仍然很麻烦。