r-如何执行data.table合并操作

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


我一直在仔细阅读data.table软件包的文档(替代data.frame,对于某些操作而言效率更高),包括Josh Reich在NYC 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

文档说:“ [[第一个参数]本身是data.table时,将类似于base :: merge调用联接,但对已排序的键使用二进制搜索。” 显然并非如此。 我可以使用data.tables将y中的其他列获取到x [y]的结果中吗? 似乎只是将x的行与键与y的键匹配,而完全忽略了y的其余部分...

Harlan asked 2020-02-14T08:35:59Z
4个解决方案
29 votes

您引用错误的文档部分。 如果您查看install.packages的文档,则会看到:

当我是data.table时,x必须有一个   键,表示将我加入x并返回   x中匹配的行。 等值联接   在i中的每一列之间执行   依次按x键中的每一列   这类似于基数R   子矩阵设置的功能   由2列矩阵和更高   包含n维的维   由n列矩阵排列

我承认对软件包(您引用的部分)的描述有些混乱,因为它似乎说可以使用“ [”-操作代替合并。 但是我认为它的意思是:如果x和y都是data.tables,我们将对索引使用联接(像合并一样调用),而不是二进制搜索。


还有一件事:

我通过install.packages安装的data.table库缺少merge.data.table method,因此使用merge将调用merge.data.frame。从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在评论中指出了这一点。

f3lix answered 2020-02-14T08:49:51Z
14 votes

感谢您的回答。 最初发布时,我错过了该主题。 自2月以来,data.table一直在移动。 1.4.1不久前已发布给CRAN,而1.5即将推出。 例如,DT()别名已替换为list(); 作为一种原始方法,它的速度要快得多,并且data.table现在继承自data.frame,因此它可以与仅接受data.frame的包(例如ggplot和lattice)一起使用,而无需进行任何转换(更快,更方便)。

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

马修

Matt Dowle answered 2020-02-14T08:50:21Z
11 votes

我认为不需要使用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

哪有什么大不了的:)

daroczig answered 2020-02-14T08:50:57Z
3 votes

我认为f3lix是正确的,并且文档有些误导。 好处是可以进行快速联接以对数据进行子集化。 之后,您仍然最终需要像上面的示例一样使用merge函数。

您将在Josh关于使用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')]
Shane answered 2020-02-14T08:51:22Z
translate from https://stackoverflow.com:/questions/2232699/how-to-do-a-data-table-merge-operation