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

问题描述 投票:22回答:3

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

那我怎么能实现呢?

r merge plyr
3个回答
16
投票

您可以在ddply包中使用plyr并将其与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

15
投票

使用类似数据库的操作很容易做到这一点。在这里,我使用包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()的第二行保持不变。


1
投票

我写了包qazxsw poi,它非常简洁地解决了这个问题:

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 参数的函数将用于冲突列对

© www.soinside.com 2019 - 2024. All rights reserved.