使用data.table进行左连接

时间:2016-01-04 19:11:08

标签: r merge data.table

假设我有两个 data.table ' s:

A:

  A  B
1: 1 12
2: 2 13
3: 3 14
4: 4 15

B:

   A  B
1: 2 13
2: 3 14

我有以下代码:

merge_test = merge(dataA, dataB, by="A", all.data=TRUE)

我明白了:

   A B.x B.y
1: 2  13  13
2: 3  14  14

但是,我想在最终合并表中的dataA中的所有行。有没有办法做到这一点?

3 个答案:

答案 0 :(得分:77)

如果您要将b的{​​{1}}值添加到B,那么最好将A加入A并更新B引用如下:

A

给出:

A[B, on = 'a', bb := i.b]

这是一个比使用> A a b bb 1: 1 12 NA 2: 2 13 13 3: 3 14 14 4: 4 15 NA 更好的appraoch,因为后者只是将结果打印到控制台。如果您希望将结果重新导入B[A, on='a'],则需要使用A,这样可以获得相同的结果。

A <- B[A, on='a']优于A[B, on = 'a', bb := i.b]的原因是内存效率。使用A <- B[A, on = 'a']A[B, on = 'a', bb := i.b]在内存中的位置保持不变:

A

另一方面,> address(A) [1] "0x102afa5d0" > A[B, on = 'a', bb := i.b] > address(A) [1] "0x102afa5d0" 创建了一个新对象,并将其作为A <- B[A, on = 'a']保存在内存中,因此在内存中有另一个位置:

A

使用> address(A) [1] "0x102abae50" > A <- B[A, on = 'a'] > address(A) [1] "0x102aa7e30" merge)会导致内存位置发生类似的变化:

merge.data.table

为了提高内存效率,最好使用&quot; update-by-reference-join&#39; 语法:

> address(A)
[1] "0x111897e00"
> A <- merge(A, B, by = 'a', all.x = TRUE)
> address(A)
[1] "0x1118ab000"

尽管这与像这样的小型数据集没有显着差异,但它确实对设计A[B, on = 'a', bb := i.b] 的大型数据集产生了影响。

可能还值得一提的是data.table的顺序保持不变。

要查看对速度和内存使用的影响,请使用一些较大的数据集进行基准测试(对于数据,请参阅下面使用数据的第二部分 - 部分):

A

给出(仅显示相关测量值):

library(bench)
bm <- mark(AA <- BB[AA, on = .(aa)],
           AA[BB, on = .(aa), cc := cc],
           iterations = 1)

因此,在此设置中,&quot; update-by-reference-join&#39; 的速度提高了9倍,内存消耗减少了11倍。

不同设置下的速度和内存使用增益可能会有所不同。

使用过的数据:

> bm[,c(1,3,5)]
# A tibble: 2 x 3
  expression                         median mem_alloc
  <bch:expr>                       <bch:tm> <bch:byt>
1 AA <- BB[AA, on = .(aa)]            4.98s     4.1GB
2 AA[BB, on = .(aa), `:=`(cc, cc)] 560.88ms   384.6MB

答案 1 :(得分:16)

你可以试试这个:

# used data
# set the key in 'B' to the column which you use to join
A <- data.table(a = 1:4, b = 12:15)
B <- data.table(a = 2:3, b = 13:14, key = 'a') 

B[A]

答案 2 :(得分:0)

为了完整起见,我为您的问题添加了table.express版本的答案。 table.express很好地将tidyverse语言扩展到了data.table,使其成为一种方便的工具,可以快速处理庞大的数据集。这是使用上述问题的数据集的解决方案:

merge_test = dataA %>% left_join(dataB, by="A")

left_join保留来自已连接数据集中dataA的所有行。