26

Windows 7 上的 R 版本 2.11.1 32 位

我有两个数据集:data_A 和 data_B:

数据_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

数据_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 中。如上面的示例,结果将是:

数据_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

那么我该如何实现呢?

4

3 回答 3

19

您可以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- 这将返回第一个 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
于 2011-04-24T12:33:42.693 回答
16

这种事情很容易通过类似数据库的操作来完成。在这里,我使用包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()保持不变。

于 2011-04-24T11:13:04.200 回答
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参数的函数将用于成对的冲突列

于 2019-03-02T23:36:25.343 回答