连接和分组两个数据表

时间:2013-04-05 09:33:16

标签: r data.table

假设我有以下两个数据表:

dt1 <- data.table(id=1:3,val1=c("a","a","b"),key="id")
#    id val1
# 1:  1    a
# 2:  2    a
# 3:  3    b


dt2 <- data.table(id=c(1:3,1:2),val2=10:14,key="id")
#    id val2
# 1:  1   10
# 2:  1   13
# 3:  2   11
# 4:  2   14
# 5:  3   12

假设dt1是由id dt2标识的人员列表,id这些人的观察列表与通讯员val2。< / p>

现在,我想为每组val1计算dt1[dt2][,mean(val2),by=val1] # val1 V1 # 1: a 12 # 2: b 12 的平均值。我明白我可以通过以下方式实现:

dt1[dt2][,mean(val2),by=val1]
dt2[dt1][,mean(val2),by=val1]

但我也在FAQ(第1.14节)中读到它效率不高(至少对于非常大的数据表)。

那么,有更好,更有效的方法吗?

编辑:另一个相关问题:我刚看到以下两行会得到相同的结果:

{{1}}

它们是等价的还是两者之间有区别?

1 个答案:

答案 0 :(得分:5)

在你的情况下,这样做是可以的。文档解释的内容是iiuc,例如在这种情况下(你没有对所有列进行分组/聚合):

dt1 <- data.table(id=1:3,val1=c("a","a","b"),key="id")
dt2 <- data.table(id=c(1:3,1:2),val2=10:14,key="id")

dt2[, val3 := rep(5:7, c(2,1,2))]
#    id val2 val3
# 1:  1   10    5
# 2:  1   13    5
# 3:  2   11    6
# 4:  2   14    7
# 5:  3   12    7

现在,假设你想为每个val2单独得到val1的平均值,那么加入所有列是没有意义的。在这种情况下,您可以:

dt1[dt2, list(val1, val2)][, mean(val2), by=val1]
#    val1 V1
# 1:    a 12
# 2:    b 12

而不是:

# gives same result but performs join on all columns
dt1[dt2][, mean(val2), by=val1]

对于您的第二个问题,我认为理解差异dt1[dt2]dt2[dt1]至关重要。为此,您的数据不是最好的例子。假设,

dt1 <- data.table(id=c(1,4,5), val1=c("a","a","b"))
dt2 <- data.table(id=c(1,2,3,6,7,8), val2=c(6,5,3,4,2,1))

setkey(dt1, "id")
setkey(dt2, "id")

dt1[dt2]id中的每个dt2获取并获取dt1中所有其他列的相应值以执行加入:

dt1[dt2]
#    id val1 val2
# 1:  1    a    6
# 2:  2   NA    5
# 3:  3   NA    3
# 4:  6   NA    4
# 5:  7   NA    2
# 6:  8   NA    1

dt2[dt1]id dt1dt2的其他列dt2[dt1] # id val2 val1 # 1: 1 6 a # 2: 4 NA a # 3: 5 NA b 中的每个dt1[dt2]执行加入:

dt2

请注意,dt2[dt1]中的值仅包含 dt1的ID。同样,id仅包含merge中的all=TRUE。在你的情况下,因为merge.data.table s完全相同(忽略它们发生的次数),所以连接都会给你相同的连接(除了列的顺序),iiuc。


只是为了完成此部分,如果您想要“完整”加入,请将merge(dt1, dt2, all = TRUE) merge(dt1, dt2, all.x = TRUE) # is equivalent to dt2[dt1] merge(dt1, dt2, all.y = TRUE) # is equivalent to dt1[dt2] 与{{1}}一起使用。 {{1}}方法已实施。

{{1}}