2016-07-26 4 views
3

データフレームを複数の列でマージする(左外部結合)方法はありますか?条件でRに外部結合を残しました

例:x, y, numとの2つのデータフレームdf1df2があります。私はdf1からのすべての行を持つデータフレームを持っていますが、条件を満たすdf2からの行だけがあります:​​OR df2$y == df2y。ここで

はサンプルデータです:

df1 <- data.frame(x = LETTERS[1:5], 
        y = 1:5, 
        num = rnorm(5), stringsAsFactors = F) 
df1 
    x y  num 
1 A 1 0.4209480 
2 B 2 0.4687401 
3 C 3 0.3018787 
4 D 4 0.0669793 
5 E 5 0.9231559 

df2 <- data.frame(x = LETTERS[3:7], 
        y = 3:7, 
        num = rnorm(5), stringsAsFactors = F) 
df2$x[4] <- NA 
df2$y[3] <- NA 
df2 
    x y  num 
1 C NA -0.7160824 
2 <NA> 4 -0.3283618 
3 E 5 -1.8775298 
4 F 6 -0.9821082 
5 G 7 1.8726288 

その後、結果があることが予想されます。

x y  num x y  num 
1 A 1 0.4209480 <NA> NA   NA 
2 B 2 0.4687401 <NA> NA   NA 
3 C 3 0.3018787 C NA -0.7160824 
4 D 4 0.0669793 <NA> 4 -0.3283618 
5 E 5 0.9231559 E 5 -1.8775298 

最も明白な解決策はsqldfパッケージを使用することです:

mergedData <- sqldf::sqldf("SELECT * FROM df1 
          LEFT OUTER JOIN df2 
          ON df1.x = df2.x 
          OR df1.y = df2.y") 

残念ながら、この単純な解決法は非常に遅く、データフレームをmとマージするのに時間がかかりますそれぞれ100k行以上の鉱石。

もう1つの選択肢は、適切なデータフレームを分割して部分的にマージすることですが、これはさらに洗練されたソリューションでも「アウトオブボックス」ソリューションですか?

+3

なぜdownvoteですか?これはよく書かれた質問です。 –

+1

私はそれをdownvoteしませんでしたが、あなたは実用的な解決策を持っているように聞こえ、あなたはそれをより速くする方法を理解したいと思っています。この場合、この質問はhttp://codereview.stackexchange.comの方が適切でしょう。 –

+3

@ Hack-R反対意見:コードレビューは(主に)パフォーマンスを改善するためのものではなく、*コード品質*向上のためのものです。問題は、そのままでは、Stack Overflowに完全に適しています。技術的な問題が解決する必要があります。 –

答えて

1

data.tableを使用する1つの方法があります。各列について、結合を実行しますが、結合全体をマテリアライズするのではなく、インデックスのみを抽出します。次に、すべての列からこれらのインデックスを組み合わせることができます(複数の一致がある場合、 。

require(data.table) 
setDT(df1) 
setDT(df2) 

foo <- function(dx, dy, cols) { 
    ix = lapply(cols, function(col) { 
     dy[dx, on=col, which=TRUE] # for each row in dx, get matching indices of dy 
            # by matching on column specified in "col" 
    }) 
    ix = do.call(function(...) pmax(..., na.rm=TRUE), ix) 
} 
ix = foo(df1, df2, c("x", "y")) # obtain matching indices of df2 for each row in df1 
df1[, paste0("col", 1:3) := df2[ix]] # update df1 by reference 
df1 
# x y   num col1 col2  col3 
# 1: A 1 2.09611034 NA NA   NA 
# 2: B 2 -1.06795571 NA NA   NA 
# 3: C 3 1.38254433 C 3 1.0173476 
# 4: D 4 -0.09367922 D 4 -0.6379496 
# 5: E 5 0.47552072 E NA -0.1962038 

あなたは、必要に応じて、data.frameに戻って、それを変換するために、​​を使用することができます。

+1

がありがとうございます。これはsqldfよりはるかに高速です。 sqldfが10KBの2つのデータフレームをマージするのに23.59秒かかりましたが、ソリューションは0.011秒で終了しました – MikeTexnik

関連する問題