1. ホーム
  2. r

[解決済み] data.tablesのX[Y]結合では、なぜ完全な外部結合や左結合ができないのですか?

2022-06-03 16:22:40

質問

これはdata.tableの結合構文に関する少し哲学的な質問です。私はdata.tablesの用途をどんどん見つけていますが、まだ勉強中です...。

結合の書式 X[Y] は非常に簡潔で、便利で効率的ですが、私の知る限り、内側joinと右外側joinしかサポートしていません。左側または完全な外側joinを取得するためには merge :

  • X[Y, nomatch = NA] -- Yの全ての行 -- 右外部結合 (デフォルト)
  • X[Y, nomatch = 0] -- XとYの両方でマッチする行のみ -- 内側join
  • merge(X, Y, all = TRUE) -- XとYの両方からすべての行を取得 -- 完全外側join
  • merge(X, Y, all.x = TRUE) -- Xのすべての行 -- 左外部結合

があれば便利そうですね。 X[Y] が4つのタイプの結合をすべてサポートしていれば便利だと思います。2つのタイプの結合しかサポートされていないのはなぜですか?

私にとっては nomatch = 0nomatch = NA のパラメータ値は、実行されるアクションに対してあまり直感的ではありません。を理解し、記憶する方が簡単です。 merge という構文があります。 all = TRUE , all.x = TRUEall.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が扱うことができる追加の結合タイプの例をいくつか提供しています。

どのように解決するのですか?

を引用すると data.table FAQ 1.11 X[Y]merge(X, Y) ?

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

Y[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 は、data.tableの中で、1つのステップでそれをすべて行ってくれます。 を使うことができます。あなたが X[Y,sum(foo*bar)] と書くと、data.tableは自動的に j 式を検査し、どのカラムを使用するかを確認します。これは、これらのカラムのみをサブセットし、他のカラムは無視されます。のカラムに対してのみメモリが作成されます。 j が使用するカラムに対してのみメモリが作成され Y の列は、各グループのコンテキスト内で標準的なRのリサイクルルールを楽しむことができます。例えば fooX にあり、バーが Y (にある他の20の列と一緒に)。 Y ). そうではなく 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)]]