如何进行data.table合并操作

Har*_*lan 49 merge r data.table

注意:这个问题和以下答案涉及data.table版本<1.5.3; v.1.5.3于2011年2月发布以解决此问题.查看更新的处理(03-2012):将外键上的SQL连接转换为R data.table语法


我一直在挖掘data.table包的文档(data.frame的替代品,对于某些操作来说效率更高),包括Josh Reich在纽约R Meetup(pdf)上关于SQL和data.table的演示,但是无法想象这完全琐碎的操作.

> x <- DT(a=1:3, b=2:4, key='a')
> x
     a b
[1,] 1 2
[2,] 2 3
[3,] 3 4
> y <- DT(a=1:3, c=c('a','b','c'), key='a')
> y
     a c
[1,] 1 a
[2,] 2 b
[3,] 3 c
> x[y]
     a b
[1,] 1 2
[2,] 2 3
[3,] 3 4
> merge(x,y)
  a b c
1 1 2 a
2 2 3 b
3 3 4 c
Run Code Online (Sandbox Code Playgroud)

文档说"当[第一个参数]本身就是一个data.table时,调用类似于base :: merge的连接,但在排序的键上使用二进制搜索." 显然情况并非如此.我可以使用data.tables将y中的其他列转换为x [y]的结果吗?看起来它只是取x的行,其中键与y的键匹配,但完全忽略了y的其余部分......

f3l*_*lix 29

您引用了错误的文档部分.如果您看一下[.data.table您将阅读的文档:

当i是data.table时,x必须有一个键,这意味着将i连接到x并返回匹配的x中的行.在i中的每列之间按顺序在x的键中的每列中执行等连接.这类似于通过2列矩阵对矩阵进行子设置的基本R功能,并且在更高维度中通过n列矩阵对n维阵列进行子集化

我承认包的描述(你引用的部分)有些令人困惑,因为它似乎说"[ - - 操作"可以用来代替合并.但我认为它的含义是:如果x和y都是data.tables,我们在索引上使用连接(它像merge一样调用)而不是二进制搜索.


还有一件事:

我安装的data.table库install.packages缺少了merge.data.table method,所以使用merge会调用merge.data.frame.从R-Forge R 安装后使用了更快的merge.data.table方法.

您可以通过检查输出来检查是否有merge.data.table方法:

methods(generic.function="merge")
Run Code Online (Sandbox Code Playgroud)

编辑[答案不再有效]:此答案涉及data.table版本1.3.在1.5.3版中,data.table的行为发生了变化,x [y]返回了预期的结果.感谢data.table的作者Matthew Dowle在评论中指出这一点.

  • X [Y]语法在2011年2月发布到CRAN的v1.5.3中已更改.请查看它的新闻,新数据.表格和更正的常见问题解答. (5认同)

Mat*_*wle 14

谢谢你的回答.我最初发布时错过了这个帖子.data.table自2月以来一直在继续.1.4.1之前已经发布到CRAN,1.5很快就会发布.例如,DT()别名已被list()替换; 作为一种原始的快得多,而且data.table现在从data.frame继承所以它与包装工作是唯一接受data.frame的例如ggplot和lattice,不需要任何转换(更快更方便).

是否可以订阅data.table标签,以便在有人发布带有该标签的问题时收到电子邮件?datatable-help列表每月增长到大约30-40条消息,但如果我能得到某种通知,我也很乐意回答这里.

马修


dar*_*zig 11

我认为base::merge不需要使用该函数,因为使用data.table连接可以快得多.例如,见下文.我用3-3列制作xydata.tables:

x <- data.table( foo = 1:5, a=20:24, zoo = 5:1 )
y <- data.table( foo = 1:5, b=30:34, boo = 10:14)
setkey(x, foo)
setkey(y, foo)
Run Code Online (Sandbox Code Playgroud)

合并两者base:mergedata.table加入以查看执行速度:

system.time(merge(x,y))
##    user  system elapsed 
##   0.027   0.000   0.023 

system.time(x[,list(y,x)])
##    user  system elapsed 
##   0.003   0.000   0.006 
Run Code Online (Sandbox Code Playgroud)

结果并不相同,因为后者有一个额外的列:

merge(x,y)
##      foo  a zoo  b boo
## [1,]   1 20   5 30  10
## [2,]   2 21   4 31  11
## [3,]   3 22   3 32  12
## [4,]   4 23   2 33  13
## [5,]   5 24   1 34  14

x[,list(x,y)]
##      foo  a zoo foo.1  b boo
## [1,]   1 20   5     1 30  10
## [2,]   2 21   4     2 31  11
## [3,]   3 22   3     3 32  12
## [4,]   4 23   2     4 33  13
## [5,]   5 24   1     5 34  14
Run Code Online (Sandbox Code Playgroud)

哪个不能大麻烦:)

  • 谢谢,这很有趣.但是,语法完全不明显!如果我要使用它,我可能会重新定义一个函数,它可以执行`function(x,y)x [,list(x,y)]`或其他东西,或者也可以删除那个额外的键列...... (3认同)
  • 我认为data.table中连接的正确语法实际上是x [y]或x [y,],即连接应该使用第一个索引.这给出了与merge相同的结果.请注意,x [y]和y [x]不必相同,即如果y包含foo中不代表x的条目.也许我错过服用点,但看到data.table [小品]联接(http://cran.r-project.org/web/packages/data.table/vignettes/datatable-intro.pdf) (2认同)