如何合并和聚合 3 个以上不同长度和名称的数据帧

how to merge AND aggregate 3+ data frames of different lengths and colnames

我有三个结构相似但列名和行数不同的数据框。

> a
        ID count    alpha
1      207     1        1
2      351     1        1
3      372     1        1
4      595     4        1
5      596     1        1
6      652     1        1

> b
        ID count     beta
1      207     1        1
2      351     1        1
3      372     1        1
4     1024     6        1

> c
        ID count     zeta
1      207     4        1
2      351     1        1
3      372     1        1
4      595     2        1

我需要创建一个新的数据框,其中包含来自两者(id、count、alpha、beta)的所有列,同时输出计数的总和。如果一个 ID 只出现在一个数据框中,它应该在相应的列中输出 0。期望的输出如下:

> abc
        ID count    alpha    beta    zeta
1      207     6        1       1       1
2      351     3        1       1       1
3      372     3        1       1       1
4      595     6        1       0       1
5      596     1        1       0       0
6      652     1        1       0       0
7     1024     6        0       1       0

我在 a 和 b 上尝试了 merge() 并得到了这个输出:

> merge(a, b, by=intersect(names(a),names(b)), all=TRUE, sort=TRUE)
    id count alpha beta
1  207     1     1    1
2  351     1     1    1
3  372     1     1    1
4  595     4     1   NA
5  596     1     1   NA
6  652     1     1   NA
7 1024     6    NA    1

我同意 0 是 NA,但我对这个输出有两个主要问题:

(1) 计数列不求和

(2) merge() 仅适用于 2 个数据框,实际上我有更多(例如 10 个)

欢迎任何建议。

以下是我的处理方法:

  1. 创建相关 data.framelist(就像将它们全部放入 list() 一样简单。
  2. 使用 rbindlist(或其他增强的 rbind 函数之一,它允许您按行将数据集绑定在一起 即使列不同 --请参阅 "plyr" 和 "dplyr" 了解 rbindlist 的其他常见替代方法)。

在这里,我使用了 "data.table" 中的 rbindlist

library(data.table)
rbindlist(list(a, b, c), use.names = TRUE, fill = TRUE)[
  , lapply(.SD, sum, na.rm = TRUE), by = ID]
#      ID count alpha beta zeta
# 1:  207     6     1    1    1
# 2:  351     3     1    1    1
# 3:  372     3     1    1    1
# 4:  595     6     1    0    1
# 5:  596     1     1    0    0
# 6:  652     1     1    0    0
# 7: 1024     6     0    1    0

我不确定这是否正是您想要处理 "alpha"、"beta"、... 列的方式。我刚刚总结了一切。


此答案中使用的示例数据:

a <- structure(list(
  ID = c(207L, 351L, 372L, 595L, 596L, 652L), 
  count = c(1L, 1L, 1L, 4L, 1L, 1L), 
  alpha = c(1L, 1L, 1L, 1L, 1L, 1L)), 
  .Names = c("ID", "count", "alpha"), 
  class = "data.frame", 
  row.names = c("1", "2", "3", "4", "5", "6"))
b <- structure(list(
  ID = c(207L, 351L, 372L, 1024L), 
  count = c(1L, 1L, 1L, 6L), beta = c(1L, 1L, 1L, 1L)), 
  .Names = c("ID", "count", "beta"), 
  class = "data.frame", row.names = c("1", "2", "3", "4"))
c <- structure(list(
  ID = c(207L, 351L, 372L, 595L), 
  count = c(4L, 1L, 1L, 2L), zeta = c(1L, 1L, 1L, 1L)), 
  .Names = c("ID", "count", "zeta"), 
  class = "data.frame", row.names = c("1", "2", "3", "4"))

这可以通过 dplyr 分阶段完成。

给出的数据:

dfA <- data.frame(c(207, 351, 372, 595, 596, 652), c(1, 1, 1, 4, 1, 1), rep(1, 6))
names(dfA) <- c('ID', 'count', 'alpha')
dfB <- data.frame(c(207, 351, 372, 1024), c(1, 1, 1, 6), rep(1, 4))
names(dfB) <- c('ID', 'count', 'beta')
dfC <- data.frame(c(207, 351, 372, 595), c(4, 1, 1, 2), rep(1, 4))
names(dfC) <- c('ID', 'count', 'zeta')

以下虽然有点难看,但可以工作:

library(dplyr)
dfT <- bind_rows(dfA, dfB, dfC)
df_1 <- dfT %>% group_by(ID) %>% summarise(sum(count))
df_F <- data.frame(df_1, as.numeric(df_i$ID %in% dfA$ID), as.numeric(df_i$ID %in% dfB$ID), as.numeric(df_i$ID %in% dfC$ID))
names(df_F) <- c("ID", "count", "alpha", "beta", "zeta")

> df_F
    ID count alpha beta zeta
1  207     6     1    1    1
2  351     3     1    1    1
3  372     3     1    1    1
4  595     6     1    0    1
5  596     1     1    0    0
6  652     1     1    0    0
7 1024     6     0    1    0