如何将R中公共列上的两个数据帧与其他列合并?

Pep*_*iCo 23 merge r plyr

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
Run Code Online (Sandbox Code Playgroud)

DATA_B

USER_A USER_B ACTION
1      13     0.17
1      14     0.27
2      11     0.25
Run Code Online (Sandbox Code Playgroud)

现在,如果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
Run Code Online (Sandbox Code Playgroud)

那我怎么能实现呢?

And*_*rie 17

您可以ddply在包中使用plyr并将其与merge:

library(plyr)
ddply(merge(data_A, data_B, all.x=TRUE), 
  .(USER_A, USER_B), summarise, ACTION=sum(ACTION))
Run Code Online (Sandbox Code Playgroud)

请注意,merge使用参数调用all.x=TRUE- 这将返回传递给第一个data.frame的所有值merge,即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
Run Code Online (Sandbox Code Playgroud)

  • 那个输出并不是OP所拥有的 - 注意你有一个额外的行比OP想要的多.我们需要`data_A`,但需要更新两个`ACTION`条目.您的答案的等效基数R将是:`aggregate(ACTION~USER_B + USER_A,data = rbind(data_A,data_B),FUN = sum)[,c(2,1,3)]`但我打了折扣因为它不是`data_A`的更新. (3认同)
  • 我错过了什么吗?OP要求对操作列值进行求和,但是这个答案不是吗? (2认同)

Rei*_*son 15

使用类似数据库的操作很容易做到这一点.在这里,我使用package sqldf进行左(外)连接,然后汇总生成的对象:

require(sqldf)
tmp <- sqldf("select * from data_A left join data_B using (USER_A, USER_B)")
Run Code Online (Sandbox Code Playgroud)

这导致:

> 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
Run Code Online (Sandbox Code Playgroud)

现在我们只需要总结两ACTION列:

data_C <- transform(data_A, ACTION = rowSums(tmp[, 3:4], na.rm = TRUE))
Run Code Online (Sandbox Code Playgroud)

这给出了期望的结果:

> 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
Run Code Online (Sandbox Code Playgroud)

这可以使用标准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
Run Code Online (Sandbox Code Playgroud)

所以我们可以用sqldf()上面的调用替换:

tmp <- merge(data_A, data_B, by = c("USER_A","USER_B"), all.x = TRUE)
Run Code Online (Sandbox Code Playgroud)

而第二线的使用transform()保持不变.