当键列数不同时合并data.table

时间:2012-10-16 18:07:15

标签: r merge data.table

我试图从文档中了解data.table中的逻辑,有点不清楚。我知道我可以尝试这个,看看会发生什么,但我想确保没有病态的情况,因此想知道逻辑是如何实际编码的。如果两个data.table个对象具有不同数量的键列,例如a有2个而b有3个,而您运行c <- a[b],则a和只需在前两个键列上合并b,或者将{3}中的第三列自动合并到b中的第三个键列?一个例子:

require(data.table)
a <- data.table(id=1:10, t=1:20, v=1:40, key=c("id", "t"))
b <- data.table(id=1:10, v2=1:20, key="id")
c <- a[b]

这应该选择与a中的id键列匹配的b行。例如,对于id==1中的bb中有2行,a中有4行,应在c中生成8行。事实确实如此:

> head(c,10)
    id  t  v v2
 1:  1  1  1  1
 2:  1  1 21  1
 3:  1 11 11  1
 4:  1 11 31  1
 5:  1  1  1 11
 6:  1  1 21 11
 7:  1 11 11 11
 8:  1 11 31 11
 9:  2  2  2  2
10:  2  2 22  2

尝试它的另一种方法是:

d <-b[a]

这应该做同样的事情:对于a中的每一行,它应该在b中选择匹配的行:因为a有一个额外的键列t,该列不应仅用于匹配和仅基于第一个键列的连接,id应该完成。看来情况就是这样:

> head(d,10)
    id v2  t  v
 1:  1  1  1  1
 2:  1 11  1  1
 3:  1  1  1 21
 4:  1 11  1 21
 5:  1  1 11 11
 6:  1 11 11 11
 7:  1  1 11 31
 8:  1 11 11 31
 9:  2  2  2  2
10:  2 12  2  2

有人可以确认吗?需要说明的是:a的第三个关键列是在任何合并中使用的,或data.table仅使用两个表中的min(length(key(DT)))

2 个答案:

答案 0 :(得分:7)

好问题。首先,正确的术语是(来自?data.table):

  

[a data.table]可能包含一个或多个列的一个键 。此键可用于行索引而不是rownames。

所以“关键”(单数)不是“关键”(复数)。目前,我们可以使用“钥匙”。但是,如果将来添加辅助密钥,则然后可以是多个密钥。每个(单数)可以有多个(复数)。

否则你绝对正确。基于其他人的反馈,以下段落在v1.8.2中得到了改进。来自?data.table

  

当我是data.table时,x必须有一个键。我使用x的键加入x,并返回匹配的x行。在i的每一列之间执行等连接到x的键中的每一列;即,i的第1列与x的第1列匹配,第2列与第2列匹配,等等。匹配是在O(log n)时间内编译的C中的二进制搜索。如果我的列少于x的键,则x的多行通常与i的每一行匹配,因为不是所有x的键列都将连接到(一个常见的用例)。如果我有比x的键更多的列,则不参与连接的i列将包含在结果中。如果我也有一个密钥,那么i是用于匹配x的密钥列的密钥列(i的密钥的第1列连接到x的密钥的第1列,第2列连接到第2列,依此类推)和二进制合并这两个表的执行情况。在所有连接中,列的名称无关紧要。 x键的列按顺序连接,从i的第1列开始,当我未键入时,或者从i的键的第1列开始。


以下评论,在v1.8.3(关于R-Forge)中,现在读取(以粗体显示):

  

当我是data.table时,x必须有一个键。我使用x的键加入x,并返回匹配的x行。在i的每一列之间执行等连接到x的键中的每一列;即,i的第1列与x的第1列匹配,第2列与第2列匹配,等等。匹配是在O(log n)时间内编译的C中的二进制搜索。如果我的列少于x的键,那么并非x的所有键列都将被连接到(一个常见的用例),并且x的许多行将(通常)与i的每一行匹配。如果我有比x的键更多的列,则不参与连接的i列将包含在结果中。如果我也有一个键,那么i是用于匹配x的键列的键列(i的键的第1列连接到x的键的第1列,第i列的第2列是x键的第2列,等等,只要更短的密钥)和两个表的二进制合并就可以执行。在所有联接中,列的名称无关紧要; x键的列按顺序连接,从i的第1列开始,当我未键入时,或者从i的键的第1列开始。 在代码中,连接列的数量由min(length(key(x)),if(haskey(i))length(key(i))else ncol(i)确定。 < / p>

答案 1 :(得分:0)

引用data.table FAQ

  

X [Y]是一个连接,使用Y(或Y的键,如果有的话)作为索引查找X的行。   Y [X]是一个连接,使用X(或X的键,如果有的话)作为索引查找Y的行。   merge(X,Y)同时执行两种方式。 X [Y]和Y [X]的行数通常不同;   而merge(X,Y)和merge(Y,X)返回的行数相同。