web-dev-qa-db-ja.com

data.tableを使用した左結合

2つのdata.tableがあるとします。

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のすべての行が必要です。これを行う方法はありますか?

37
lord12

これを試すことができます:

# 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]
19
danas.zuokas

bB値をAに追加する場合は、ABと結合し、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

後者はコンソールに結果を出力するだけなので、これは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"

mergemerge.data.table)を使用すると、メモリの場所が同様に変更されます。

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

したがって、メモリ効率のために、 'update-by-reference-join'構文を使用することをお勧めします。

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

これは、このような小さなデータセットでは目立った違いはありませんが、data.tableが設計された大きなデータセットでは違いを生じます。

おそらく言及する価値があるのは、Aの順序が同じままであることです。


速度とメモリ使用への影響を確認するために、いくつかのより大きなデータセットでベンチマークしてみましょう(データについては、以下のused data-sectionの2番目の部分を参照) :

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

これにより、関連する測定値のみが表示されます:

> 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

したがって、このセットアップでは、 'update-by-reference-join'は約9倍速く、11倍少ないメモリを消費します。

注:速度とメモリ使用量のゲインは、セットアップによって異なる場合があります。


使用データ:

# initial datasets
A <- data.table(a = 1:4, b = 12:15)
B <- data.table(a = 2:3, b = 13:14)

# large datasets for the benchmark
set.seed(2019)
AA <- data.table(aa = 1:1e8, bb = sample(12:19, 1e7, TRUE))
BB <- data.table(aa = sample(AA$a, 2e5), cc = sample(2:8, 2e5, TRUE))
92
Jaap