web-dev-qa-db-ja.com

Rの共通列の2つのデータフレームを他の合計とマージするにはどうすればよいですか?

Rバージョン2.11.1Windows7の32ビット

Data_Aとdata_Bの2つのデータセットを取得しました。

data_A

USER_A USER_B ACTION
1      11     0.3
1      13     0.25
1      16     0.63
1      17     0.26
2      11     0.14
2      14     0.28

data_B

USER_A USER_B ACTION
1      13     0.17
1      14     0.27
2      11     0.25

ここで、USER_AとUSER_Bが等しい場合、data_BのACTIONをdata_Aに追加します。上記の例のように、結果は次のようになります。

data_A

USER_A USER_B ACTION
1      11     0.3
1      13     0.25+0.17
1      16     0.63
1      17     0.26
2      11     0.14+0.25
2      14     0.28

では、どうすればそれを達成できますか?

24
PepsiCo

パッケージddplyplyrを使用し、それをmergeと組み合わせることができます。

library(plyr)
ddply(merge(data_A, data_B, all.x=TRUE), 
  .(USER_A, USER_B), summarise, ACTION=sum(ACTION))

mergeがパラメータall.x=TRUEで呼び出されることに注意してください。これにより、mergeに渡された最初のdata.frameのすべての値が返されます。つまり、data_A:

  USER_A USER_B ACTION
1      1     11   0.30
2      1     13   0.25
3      1     16   0.63
4      1     17   0.26
5      2     11   0.14
6      2     14   0.28
17
Andrie

この種のことは、データベースのような操作で非常に簡単に行うことができます。ここでは、パッケージsqldfを使用して左(外部)結合を実行し、結果のオブジェクトを要約します。

_require(sqldf)
tmp <- sqldf("select * from data_A left join data_B using (USER_A, USER_B)")
_

その結果、次のようになります。

_> tmp
  USER_A USER_B ACTION ACTION
1      1     11   0.30     NA
2      1     13   0.25   0.17
3      1     16   0.63     NA
4      1     17   0.26     NA
5      2     11   0.14   0.25
6      2     14   0.28     NA
_

ここで、2つのACTION列を合計する必要があります。

_data_C <- transform(data_A, ACTION = rowSums(tmp[, 3:4], na.rm = TRUE))
_

これにより、望ましい結果が得られます。

_> data_C
  USER_A USER_B ACTION
1      1     11   0.30
2      1     13   0.42
3      1     16   0.63
4      1     17   0.26
5      2     11   0.39
6      2     14   0.28
_

これは、標準のR関数mergeを使用して実行できます。

_> merge(data_A, data_B, by = c("USER_A","USER_B"), all.x = TRUE)
  USER_A USER_B ACTION.x ACTION.y
1      1     11     0.30       NA
2      1     13     0.25     0.17
3      1     16     0.63       NA
4      1     17     0.26       NA
5      2     11     0.14     0.25
6      2     14     0.28       NA
_

したがって、上記のsqldf()呼び出しを次のように置き換えることができます。

_tmp <- merge(data_A, data_B, by = c("USER_A","USER_B"), all.x = TRUE)
_

transform()を使用する2行目は同じままです。

私はパッケージを書きました safejoin これはこれを非常に簡潔に解決します:

# devtools::install_github("moodymudskipper/safejoin")
library(safejoin)
safe_left_join(data_A,data_B, by = c("USER_A", "USER_B"), 
               conflict = ~ .x+ ifelse(is.na(.y),0,.y))
#   USER_A USER_B ACTION
# 1      1     11   0.30
# 2      1     13   0.42
# 3      1     16   0.63
# 4      1     17   0.26
# 5      2     11   0.39
# 6      2     14   0.28

競合する場合、conflict引数に指定された関数は、競合する列のペアで使用されます

2