如何进行data.table合并操作

时间:2010-02-09 21:34:52

标签: r merge data.table

注意:这个问题和以下答案涉及data.table版本< 1.5.3; v.1.5.3于2011年2月发布以解决此问题。查看最近的治疗(03-2012):Translating SQL joins on foreign keys to R data.table syntax


我一直在挖掘data.table package的文档(替换data.frame,对于某些操作来说效率更高),包括Josh Reich's presentation on SQL and data.table at the NYC R Meetup(pdf),但无法想象这一点完全琐碎的操作。

> 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

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

4 个答案:

答案 0 :(得分:28)

您引用了错误的文档部分。如果你看一下[.data.table的文档,你会看到:

  

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

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


还有一件事:

我通过install.packages安装的data.table库缺少merge.data.table method,因此使用merge会调用merge.data.frame。安装package from R-Forge R后,使用了更快的merge.data.table方法。

您可以通过检查输出:

来检查是否有merge.data.table方法
methods(generic.function="merge")

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

答案 1 :(得分:14)

感谢您的回答。我最初发布时错过了这个帖子。 data.table自2月以来一直在继续。 1.4.1之前已经发布到CRAN,1.5很快就会发布。例如,DT()别名已被list()替换;作为一个原语,它更快,data.table现在继承自data.frame,因此它适用于接受data.frame(如ggplot和lattice)的包,无需任何转换(更快更方便) )。

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

马修

答案 2 :(得分:11)

我认为不需要使用base::merge函数,因为使用data.table联接可以快得多。例如。请参阅以下内容。我使用3-3列制作xy data.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)

并与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 

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

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

这不会造成大麻烦:)

答案 3 :(得分:3)

我认为f3lix是正确的,文档有点误导。好处是快速连接以对数据进行子集化。您最后仍需要使用merge函数,如上例所示。

您将在Josh's presentation on using data.table中看到这是他的示例运行的方式。他首先将其中一个data.tables子集,然后进行合并:

library(data.table)
sdt <- DT(series, key='series_id')
ddt <- DT(data, key='series_id')
u <- sdt[ grepl('^[A-Z]{2}URN', fred_id) & !grepl('DSURN', fred_id) ]
d <- ddt[ u, DT(min=min(value)), by='series_id', mult='all']
data <- merge(d,series)[,c('title','min','mean','max')]