在R中使用data.table进行外连接

16

想知道是否有一种有效的方法可以在数据表格中进行外连接操作,例如:

a <- data.table(a=c(1,2,3),b=c(3,4,5))
b <- data.table(a=c(1,2),k=c(1,2))
merge(a,b,by="a",all.x=T)

这样做可以正常工作,但与更大的数据使用内部连接相比效率不高,因为下面的方法非常快,而上面的方法非常慢。

setkey(a,a)
setkey(b,a)
a[b,]

在第一种情况下,ab是未键掉的,所以merge需要先将它们键掉(作为本地副本(有点像)存储在合并内部,因为它不想改变调用范围内的ab)。在第二种情况下,您已经通过键掉它们来更改了ab(您是否包括执行此操作的时间?),然后a[b]很快。但即使如此,我还是很惊讶有如此大的差异。merge应该与x[y]相当可比。请在讨论时间时说明版本信息:您使用的是v1.8.6吗?而且,您的“非常快”和“非常慢”可能是我认为“相似”的想法!实际时间是多少? - Matt Dowle
在进行基准测试时很容易出现错误或不当的情况,因此在发表任何言论之前,我们一定需要看到您的计时方法。 - Matt Dowle
我无法为此提供时间,因为第一个在内存中爆炸并导致 R 会话崩溃(连接约19m行)。我将使用较小的数据集进行基准测试,并发布结果。(我正在使用1.8.2版本) - jamborta
在较小的数据集上,这将非常好。我们经常看到用户报告 merge(包括基本合并和 data.table 合并)在意外请求笛卡尔积时会出现错误。也许我们可以在其中设置一些陷阱来帮助检测和捕捉不正确的用法。只是一个猜测。似乎有时人们尝试使用 merge,而实际上他们需要的是 cbind - Matt Dowle
1个回答

11

b[a,] 是你正在寻找的 "outer join"。

更多具体信息请看 ?merge.data.table


1
谢谢!所以a[b,]或b[a,]本质上是左连接(在SQL术语中)?我一直认为它是内连接。 - jamborta
@jamborta 请查看常见问题解答2.16 (nomatch = 0|NA)。 - Matt Dowle
2
谢谢Matthew,这解释得很清楚。我猜这样做不能实现完全外连接(只能左外连接和内连接)? - jamborta
2
@jamborta 正确。但是你可以使用 X[Y]Y[X] 来表示左或右。它源自于“按-不按”特性(类似于 SQL 中的 CROSS APPLY 和 OUTER APPLY)。这个想法是,j 对于 i 的每一行都会运行。在全外连接的情况下,这没有意义。如果需要全外连接,那么就可以使用 merge。话虽如此,越来越多的连接类型被要求,在这个详细的问题中提出了这个问题(https://dev59.com/bWcs5IYBdhLWcg3wh0f7),这个问题已经列入考虑范围。 - Matt Dowle
有没有比merge.data.table更快的全外连接替代方案? - Moysey Abramowitz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接