簡體   English   中英

如何將R中公共列上的兩個數據幀與其他列合並?

[英]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:

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

那我怎么能實現呢?

您可以在包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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM