![](/img/trans.png)
[英]How to merge two data frames on common columns in R with sum of others using dplyr package
[英]How to merge two data frames on common columns in R with sum of others?
R版本2.11.1在Windows 7上為32位
我有兩個數據集:data_A和data_B:
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
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。 如上例所示,結果將是:
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
那我怎么能實現呢?
您可以在包plyr
使用ddply
並將其與merge
結合使用:
library(plyr)
ddply(merge(data_A, data_B, all.x=TRUE),
.(USER_A, USER_B), summarise, ACTION=sum(ACTION))
請注意,使用參數all.x=TRUE
調用merge
- 這將返回傳遞給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
使用類似數據庫的操作很容易做到這一點。 在這里,我使用包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
現在我們只需要總結兩個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()
的第二行保持不變。
我編寫了包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
參數的函數用於沖突列對
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.