2010-02-09 82 views
43

注意:这个问题和下面的答案引用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合并操作


我已经通过了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,联接调用类似于基地::合并,但使用的排序键二进制搜索。”显然情况并非如此。我可以通过data.tables将y中的其他列转换为x [y]的结果吗?它似乎只是采取x的行,其中密钥匹配y的关键,但完全忽略y的其余部分...

+2

2011年2月发布给CRAN的v1.5.3解决了这个问题。请查看它的NEWS,new?data.table和更正的常见问题解答。 – 2011-03-24 12:30:35

回答

27

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

当我是一个data.table,x必须有一个 键,表示加入我x和回报 在X匹配的行。依次加入 ,将i 中的每列与x的键中的每列按顺序进行匹配。 这类似于基础R 功能由2列矩阵子集划分的矩阵 的,并且在较高的 尺寸由n列矩阵

我承认子集划分的n维阵列 软件包(引用的部分)的描述有些令人困惑,因为它似乎表示可以使用“[”操作而不是合并。但我认为它说的是:如果x和y都是data.tables,我们在索引上使用连接(这是像合并一样调用)而不是二进制搜索。


一件事:

我安装通过install.packages失踪的merge.data.table method,所以使用merge会叫merge.data.frame的data.table库。安装后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]返回预期结果。谢谢Matthew Dowle,作者data.table,在评论中指出这一点。

+0

啊。看起来好像CRAN上的版本是1.2版本,而R-Forge上的版本是1.3版本。 “合并”方法显然是在1.3中加入的。根据我所能看到的R-Forge的情况,该方法增加了8个月前的内容,所以我不知道为什么它不在CRAN上! – Harlan 2010-02-10 23:02:21

+5

X [Y]语法在2011年2月发布到CRAN的v1.5.3中进行了更改。请参阅NEWS,new?data.table和更正的常见问题解答。 – 2011-03-24 12:32:36

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')] 
+0

谢谢,谢恩。我非常困惑,因为我知道(或者我以为我知道)'合并'不会利用'data.table'的优点。 – Harlan 2010-02-10 23:04:24

14

感谢您的回答。当它最初发布时,我错过了这个线程。自2月份以来,data.table已经开始运行。 1.4.1刚刚发布给CRAN,1.5版即将发布。例如,DT()别名已被替换为list();作为一个原语其速度更快,data.table现在继承data.frame,因此它可以与只包含的包接受数据帧,如ggplot和lattice,而无需任何转换(更快,更方便)。

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

马修

+1

嗨,谢谢你的提示!是的,这绝对有可能。点击屏幕右上角的'data.table'标记框,然后滚动到底部,直到看到RSS图标,并使用它来订阅带有此标记的问题。 – Harlan 2010-07-27 20:58:30

+0

谢谢哈伦。我现在订阅了。 – 2010-07-28 10:17:12

9

我认为使用base::merge功能是不需要的,因为使用data.table联接可以是快了很多。例如。请参阅以下内容。我做xy data.tables有3-3列:

> 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:merge合并双方和data.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

谢谢,这很有趣。虽然一个完全不明显的语法!如果我要使用它,我可能会重新定义一个函数,该函数会执行'function(x,y)x [,list(x,y)]'或其他东西,也许会删除额外的键列... – Harlan 2011-03-06 19:35:45

+2

我认为正确data.table中连接的语法实际上是x [y]或x [y,],即联接应该使用第一个索引。这与合并结果相同。请注意,x [y]和y [x]不必相同,即如果y包含foo中不代表x的条目。也许我已经错过了一些,但看到在data.table [vignette]中加入(http://cran.r-project.org/web/packages/data.table/vignettes/datatable-intro.pdf) – cboettig 2012-05-22 00:32:25

+1

以上x [,list(x,y)]对我不起作用。我试过x [,c(x,y)],它工作。我不确定它是否合理。 – bala 2013-11-06 10:47:40