问题描述
我想知道为什么 data.table 的左连接没有给我多个匹配,似乎有一些奇怪的内置“无重复”,这并没有真正使它成为左连接,是吗?
数据:
test=data.table(mtcars[1,])
test2=data.table(mtcars[c(1,1),])
data.table:
test[test2,on = c(carb = "carb"),wt2 := i.wt]
dplyr:
test %>% left_join(test2 %>% select(carb,wt) %>% rename(wt2 = wt),by = "carb")
dplyr 给了我正确的两行结果,但 data.table 只给了我一行。这是怎么回事?
解决方法
在这里参考@Frank 的回答: Which data.table syntax for left join (one column) to prefer
,以及@Jaap 的回答: left join using data.table
我认为这对于真正寻找左连接并来到这个社区寻求答案的人来说是危险的领域。链接中提供的参考示例更新(使用 :=
的解决方案)(此处 OP 使用的方法相同)并不是真正的左连接。左连接返回左表中的所有记录,以及右表中匹配的记录,但是我们讨论的这个 data.table
语法实际上并没有返回右表中的所有匹配记录,因此不是左连接.
data.table 文档清楚地说明左连接是:
X[DT,on="x"] # left join
,这将使正确的 data.table OP 正在寻找:
test[test2,on="carb"] # or,test[test2[,wt2 := wt][,c("carb","wt2")],on="carb"] # left join
@Jaap 在他的回答中解释了通过引用加入(使用 :=
表示法)和常规左加入之间的区别:
虽然这对小数据集没有显着差异 像这样,它确实对大型数据集产生了影响 data.table 是设计的。
在我看来,这里有两个陈述很吓人。一是确实存在明显差异 - 结果 - 因为使用两种方法的结果不同(虽然我理解他在谈论速度,编辑:as @ jangorecki 指出,这与速度无关,而与内存使用有关。通过引用更新不会在内存中创建第二个对象)。第二件事是假设(在我看来,恭敬地)是,如果有人正在处理大型数据集并且意图进行左连接,那么我从未遇到任何不想要所有数据的人匹配右表。
我不知道如何使用“data.table”中的引用更新来实际执行左连接。我的推理是 :=
被定义为仅用于 j (data.table
语法)。它通过引用添加或更新或删除列。它根本不复制内存的任何部分。但是因为如果我们在右表中获得多个匹配项(如果我们打算进行实际的左连接),我们可能必须向左表添加额外的行,所以我不认为 {{可以使用 1}} 运算符,因为它适用于列
相当于 dplyr
连接
test %>% left_join(test2 %>% select(carb,wt) %>% rename(wt2 = wt),by = "carb")
在data.table
是
test[test2[,.(carb,wt2 = wt)],on = 'carb']