139

これは、data.table結合構文に関する哲学的な質問です。data.tablesの用途はますます増えていますが、それでも学習しています...

data.tablesの結合形式X[Y]は非常に簡潔で、便利で効率的ですが、私が知る限り、内部結合と右外部結合のみをサポートしています。左または完全な外部結合を取得するには、次を使用する必要がありますmerge

  • X[Y, nomatch = NA]--Yのすべての行--右外部結合(デフォルト)
  • X[Y, nomatch = 0]--XとYの両方に一致する行のみ--内部結合
  • merge(X, Y, all = TRUE)--XとYの両方のすべての行--完全外部結合
  • merge(X, Y, all.x = TRUE)--Xのすべての行-左外部結合

X[Y]結合形式が4種類すべての結合をサポートしていれば便利だと思います。2種類の結合のみがサポートされている理由はありますか?

私にとって、nomatch = 0およびnomatch = NAパラメーターの値は、実行されているアクションに対してあまり直感的ではありません。merge構文を理解して覚える方が簡単です: all = TRUE、、。操作はよりもはるかに似ているので、関数のパラメーターではなく、結合の構文を使用してみませんか?all.x = TRUEall.y = TRUEX[Y]mergematchmergematchnomatch

4つの結合タイプのコード例を次に示します。

# sample X and Y data.tables
library(data.table)
X <- data.table(t = 1:4, a = (1:4)^2)
setkey(X, t)
X
#    t  a
# 1: 1  1
# 2: 2  4
# 3: 3  9
# 4: 4 16

Y <- data.table(t = 3:6, b = (3:6)^2)
setkey(Y, t)
Y
#    t  b
# 1: 3  9
# 2: 4 16
# 3: 5 25
# 4: 6 36

# all rows from Y - right outer join
X[Y]  # default
#  t  a  b
# 1: 3  9  9
# 2: 4 16 16
# 3: 5 NA 25
# 4: 6 NA 36

X[Y, nomatch = NA]  # same as above
#    t  a  b
# 1: 3  9  9
# 2: 4 16 16
# 3: 5 NA 25
# 4: 6 NA 36

merge(X, Y, by = "t", all.y = TRUE)  # same as above
#    t  a  b
# 1: 3  9  9
# 2: 4 16 16
# 3: 5 NA 25
# 4: 6 NA 36

identical(X[Y], merge(X, Y, by = "t", all.y = TRUE))
# [1] TRUE

# only rows in both X and Y - inner join
X[Y, nomatch = 0]  
#    t  a  b
# 1: 3  9  9
# 2: 4 16 16

merge(X, Y, by = "t")  # same as above
#    t  a  b
# 1: 3  9  9
# 2: 4 16 16

merge(X, Y, by = "t", all = FALSE)  # same as above
#    t  a  b
# 1: 3  9  9
# 2: 4 16 16

identical( X[Y, nomatch = 0], merge(X, Y, by = "t", all = FALSE) )
# [1] TRUE

# all rows from X - left outer join
merge(X, Y, by = "t", all.x = TRUE)
#    t  a  b
# 1: 1  1 NA
# 2: 2  4 NA
# 3: 3  9  9
# 4: 4 16 16

# all rows from both X and Y - full outer join
merge(X, Y, by = "t", all = TRUE)
#    t  a  b
# 1: 1  1 NA
# 2: 2  4 NA
# 3: 3  9  9
# 4: 4 16 16
# 5: 5 NA 25
# 6: 6 NA 36

更新:data.table v1.9.6でon=構文が導入され、主キー以外のフィールドでアドホック結合が可能になりました。質問に対するjangoreckiの答えデータフレーム(内側、外側、左、右)を結合(マージ)する方法は?data.tableが処理できる追加の結合タイプの例をいくつか示します。

4

3 に答える 3

79

FAQ 1.11から引用するにはdata.table の違いは何ですか?X[Y]merge(X, Y)

X[Y]は結合であり、Y(またはYのキーがある場合はYのキー)をインデックスとして使用してXの行を検索します。

Y[X]結合であり、X(またはXのキーがある場合はXのキー)を使用してYの行を検索します

merge(X,Y)両方の方法を同時に実行します。X[Y]との行数はY[X]通常異なりますが、とによって返される行数はmerge(X,Y)同じmerge(Y,X)です。

しかし、それは要点を見逃しています。ほとんどのタスクでは、結合またはマージ後にデータに対して何かを実行する必要があります。なぜデータのすべての列をマージし、後でそれらの小さなサブセットのみを使用するのですか?あなたは提案するかもしれませんが merge(X[,ColsNeeded1],Y[,ColsNeeded2])、それはプログラマーがどの列が必要かを理解することを要求します。X[Y,j] in data.tableは、これらすべてを1つのステップで実行します。を書き込むX[Y,sum(foo*bar)]と、data.tableはj式を自動的に検査して、使用する列を確認します。それらの列のみをサブセット化します。その他は無視されます。jメモリは、使用する列に対してのみ作成され、列はY、各グループのコンテキスト内で標準のRリサイクルルールを利用します。にがあり、バーがにあるとfooしましょう(他の20列と一緒に)。そうじゃないXYYX[Y,sum(foo*bar)]すべてを無駄にマージした後にサブセットをマージするよりも、プログラミングと実行が高速ですか?


の左外側結合が必要な場合X[Y]

le <- Y[X]
mallx <- merge(X, Y, all.x = T)
# the column order is different so change to be the same as `merge`
setcolorder(le, names(mallx))
identical(le, mallx)
# [1] TRUE

完全な外部結合が必要な場合

# the unique values for the keys over both data sets
unique_keys <- unique(c(X[,t], Y[,t]))
Y[X[J(unique_keys)]]
##   t  b  a
## 1: 1 NA  1
## 2: 2 NA  4
## 3: 3  9  9
## 4: 4 16 16
## 5: 5 25 NA
## 6: 6 36 NA

# The following will give the same with the column order X,Y
X[Y[J(unique_keys)]]
于 2012-10-08T00:18:23.577 に答える
26

@mnelの答えは的確なので、その答えを受け入れてください。これはフォローアップであり、コメントするには長すぎます。

mnelが言うように、左/右の外部結合は、スワッピングYXY[X]-vs-によって取得されX[Y]ます。したがって、4つの結合タイプのうち3つがその構文でサポートされ、2つはサポートされません。iiuc。

4番目を追加するのは良い考えのようです。full=TRUEまたは(最適な引数名がわからない場合)を追加するとします。それまでは発生していなかったのでboth=TRUE、FAQ1.12のBUT後の理由で役立ちます。新機能のリクエストが追加され、ここにリンクされました。ありがとうございます:merge=TRUEX[Y,j,merge=TRUE]

FR#2301:merge()と同様に、X[Y]とY[X]の両方の結合にmerge=TRUE引数を追加します。

最近のバージョンは高速化さmerge.data.tableれています(たとえば、キーをより効率的に設定するために内部で浅いコピーを取得することによって)。そのため、私たちは近づき、完全な柔軟性を実現するためにすべてのオプションをユーザーに提供しようとしてmerge()います。X[Y]両方の長所と短所があります。もう1つの優れた機能リクエストは次のとおりです。

FR#2033:by.xとby.yをmerge.data.tableに追加します

他にいらっしゃいましたら、どうぞよろしくお願いします。

質問のこの部分によって:

match関数のnomatchパラメーターではなく、結合にマージ構文を使用してみませんか?

merge()構文とその3つの引数が必要な場合はall、の代わりall.xall.yそれを使用してX[Y]ください。すべてのケースをカバーする必要があると思います。それとも、なぜ議論が単一nomatchであるのかということ[.data.tableですか?もしそうなら、それはFAQ 2.14を考えると自然に思えた方法です:「data.tableがベースのA [B]構文に触発されている理由をさらに説明できますか?」ただし、現在とnomatchは2つの値のみを取ります。これは、負の値が何かを意味するように拡張できます。または、12は、たとえば、12番目の行の値を使用してNAを埋めることを意味します。または、将来的には、ベクトルまたはそれ自体でさえも可能になります。0NAnomatchdata.table

うーん。by-without-byはmerge=TRUEとどのように相互作用しますか?おそらく、これをdatatable-helpに引き継ぐ必要があります。

于 2012-10-08T09:30:46.093 に答える
19

この「答え」は議論の提案です。私のコメントに示されているように、join[.data.table() にパラメーターを追加して、追加のタイプの結合を有効にすることをお勧めしますX[Y,j,join=string]。4 種類の通常の結合に加えて、3 種類の排他的結合とクロス結合もサポートすることをお勧めします。

さまざまな結合タイプのjoin文字列値 (およびエイリアス) は、次のように提案されています。

  1. "all.y"および"right"-- 右結合、現在の data.table デフォルト (nomatch=NA) - X 一致がない NA を持つすべての Y 行。
  2. "both"そして"inner" -- 内部結合 (nomatch=0) - X と Y が一致する行のみ。

  3. "all.x"および"left" -- 左結合 - Y が一致しない X、NA からのすべての行:

  4. "outer"および"full" -- 完全外部結合 - X および Y からのすべての行、一致しない NA

  5. "only.x"および"not.y"-- 一致する Y がない X 行を返す非結合または逆結合

  6. "only.y" および"not.x"-- X 一致がない場合に Y 行を返す非結合または非結合
  7. "not.both"-- 他のテーブルと一致しない X 行と Y 行を返す排他的結合、つまり排他的論理和 (XOR)
  8. "cross"-- X の各行が Y の各行に一致する交差結合またはデカルト積

デフォルト値はjoin="all.y"、現在のデフォルトに対応する です。

「all」、「all.x」、「all.y」の文字列値はmerge()パラメータに対応します。"right"、"left"、"inner"、および "outer" の文字列は、SQL ユーザーにより適している場合があります。

"both" と "not.both" の文字列が現時点での私の最良の提案ですが、誰かが内部結合と排他的結合に対してより良い文字列の提案をしているかもしれません。(「排他的」という用語が正しいかどうかはわかりません。「XOR」結合に適切な用語があれば修正してください。)

の使用は、または非結合構文join="not.y"の代替であり、 (私にとっては)より明確ですが、それらが同じかどうかはわかりません (data.table バージョン 1.8.3 の新機能)。X[-Y,j]X[!Y,j]

クロス結合は便利な場合もありますが、data.table パラダイムには適合しない場合があります。

于 2012-10-31T13:50:08.237 に答える