web-dev-qa-db-ja.com

data.tablesのX [Y]結合が完全外部結合または左結合を許可しないのはなぜですか?

これは、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 = TRUE_、_all.y = TRUE_。 _X[Y]_操作はmergeよりもmatchによく似ているため、merge関数のmatchパラメーターではなく、nomatch構文を結合に使用してください。 ?

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が処理できる追加の結合タイプの例を示します。

112
Douglas Clark

_data.table_から引用するには FAQ 1.11 _X[Y]_とmerge(X, Y)?の違いは何ですか?

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

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

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

しかし、要点を見逃しています。ほとんどのタスクでは、結合またはマージ後にデータに対して何かを行う必要があります。データのすべての列をマージし、後でそれらの小さなサブセットのみを使用するのはなぜですか? merge(X[,ColsNeeded1],Y[,ColsNeeded2])を提案することもできますが、それにはプログラマーがどの列が必要かを判断する必要があります。 data.tableの_X[Y,j_]は、すべてを1ステップで行います。 X[Y,sum(foo*bar)]を記述すると、data.tableはj式を自動的に検査して、使用する列を確認します。これらの列のみがサブセット化されます。その他は無視されます。メモリはjが使用する列に対してのみ作成され、Y列は各グループのコンテキスト内で標準のRリサイクルルールに従います。 fooXにあり、barがYにあるとしましょう(Yの他の20列とともに)。 X[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)]]
_
66
mnel

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

Mnelが言うように、左右の外部結合はYXを交換することで取得できます:_Y[X]_ -vs- _X[Y]_。そのため、2つのiiucではなく、4つの結合タイプのうち3つがその構文でサポートされています。

4番目を追加するのは良い考えのようです。 _full=TRUE_または_both=TRUE_または_merge=TRUE_(最適な引数名がわからない?)を追加すると、_X[Y,j,merge=TRUE]_はFAQ 1.12。新しい機能のリクエストがここに追加され、リンクされています。ありがとう:

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

最近のバージョンは_merge.data.table_を高速化しました(たとえば、キーをより効率的に設定するために浅いコピーを内部的に取得することにより)。そのため、merge()と_X[Y]_を近づけ、すべてのオプションをユーザーに提供して柔軟性を高めようとしています。両方の長所と短所があります。別の優れた機能要求は次のとおりです。

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

他に何かがある場合は、それらを続けてください。

質問のこの部分で:

一致関数のnomatchパラメータではなく、結合にマージ構文を使用しないのはなぜですか?

merge()構文とその3つの引数all、_all.x_および_all.y_を好む場合は、_X[Y]_の代わりにそれを使用してください。すべてのケースをカバーすべきだと思います。または、引数が_[.data.table_の単一のnomatchである理由を意味しましたか?もしそうなら、それはFAQ 2.14: "なぜdata.tableがbaseのA [B]構文に触発されているのか、さらに説明できますか?"ですが、nomatchは、現在_0_とNAの2つの値のみを取ります。これは、負の値が何かを意味するように拡張できます。たとえば、12は、12番目の行の値を使用してNAを埋めることを意味します、またはnomatchは将来的にはベクトルまたはそれ自体が_data.table_になる可能性があります。

ふむby-without-byは、merge = TRUEとどのように対話しますか?おそらく datatable-help に引き継ぐ必要があります。

21
Matt Dowle

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

さまざまな結合タイプの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()パラメーターに対応します。 「右」、「左」、「内部」、および「外部」の文字列は、SQLユーザーにより適している場合があります。

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

_join="not.y"_の使用は_X[-Y,j]_または_X[!Y,j]_の非結合構文の代替であり、おそらくより明確です(私にとっては) data.tableバージョン1.8.3)。

クロスジョインは便利な場合もありますが、data.tableパラダイムに収まらない場合があります。

15
Douglas Clark