web-dev-qa-db-ja.com

data.tableマージ操作の実行方法

注:この質問と次の回答は、data.tableバージョン<1.5.3を参照しています。 v。1.5.3は、この問題を解決するために2011年2月にリリースされました。より最近の処理(2012年3月)を参照してください。 外部キーのSQL結合をR data.table構文に変換


data.tableパッケージ (特定の操作でより効率的であるdata.frameの置き換え)のドキュメントを掘り下げてきましたが、これには Josh ReichによるSQLとデータに関するプレゼンテーションが含まれます。 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である場合、base :: mergeと同様に結合が呼び出されますが、ソートされたキーでバイナリ検索を使用します」と述べています。明らかにそうではありません。 data.tablesを使用して、yから他の列をx [y]の結果に取得できますか?キーがyのキーと一致するxの行だけを取得しているように見えますが、残りのyは完全に無視しています...

49
Harlan

ドキュメントの間違った部分を引用しています。 [.data.tableのドキュメントを見ると、次のようになります。

Iがdata.tableの場合、xにはキーが必要です。つまり、iをxに結合し、が一致するxの行を返します。 iの各列とxのキーの各列の間で順番に等結合が実行されます。これは、2列のマトリックスでマトリックスをサブ設定し、高次元ではn列のマトリックスでn次元配列をサブセット化するベースR機能に似ています。

パッケージ(あなたが引用した部分)の説明は、やや紛らわしいことを認めます。なぜなら、「[」操作をマージの代わりに使用できると言っているからです。しかし、私はそれが言っていると思います:xとyが両方ともdata.tablesである場合、バイナリ検索の代わりにインデックス(結合のように呼び出される)で結合を使用します。


もう一つ:

install.packages経由でインストールしたdata.tableライブラリにはmerge.data.table methodがないため、mergeを使用するとmerge.data.frameが呼び出されます。 R-Forgeのパッケージ Rをインストールした後、Rはより高速なmerge.data.tableメソッドを使用しました。

以下の出力を確認することにより、merge.data.tableメソッドがあるかどうかを確認できます。

methods(generic.function="merge")

EDIT [回答は無効になりました]:この回答はdata.tableバージョン1.3を参照しています。バージョン1.5.3では、data.tableの動作が変更され、x [y]は期待される結果を返します。 Matthew Dowle 、data.tableの作者、コメントでこれを指摘してくれてありがとう。

29
f3lix

答えてくれてありがとう。このスレッドは、最初に投稿されたときに見逃していました。 data.tableは2月から移動しています。 1.4.1は少し前にCRANにリリースされ、1.5はまもなく公開されます。たとえば、DT()エイリアスはlist()に置き換えられました。プリミティブとしてはるかに高速であり、data.tableはdata.frameから継承されるため、変換を必要とせずにggplotやラティスなどのdata.frameを受け入れるonlyのパッケージで動作します(より高速で便利です) )。

Data.tableタグをサブスクライブして、誰かがそのタグで質問を投稿したときにメールを受け取ることは可能ですか? datatable-helpリストは月に約30〜40のメッセージに成長しましたが、何らかの通知を受け取ることができれば、ここでもお答えできてうれしいです。

マシュー

14
Matt Dowle

base::merge結合を使用するとはるかに高速になるため、data.table関数を使用する必要はないと思います。例えば。以下を参照してください。 xおよびy 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:mergedata.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 

後者には1つの追加列があるため、結果は同一ではありません。

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

それは大きなトラブルを起こすことができませんでした:)

11
daroczig

F3lixは正しいと思いますし、ドキュメントは少し誤解を招くかもしれません。利点は、高速結合を実行してデータをサブセット化することです。上記の例のように、後で最終的にmerge関数を使用する必要があります。

data.tableの使用に関するJoshのプレゼンテーション で、これが彼の例を実行する方法であることがわかります。彼は最初にdata.tablesの1つをサブセットし、次にマージを行います。

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')]
3
Shane