【问题标题】:how to merge AND aggregate 3+ data frames of different lengths and colnames如何合并和聚合 3+ 个不同长度和列名的数据帧
【发布时间】:2015-03-12 04:27:48
【问题描述】:

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

> 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)的所有列的新数据框,同时输出 count 的总和。如果一个 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 个)

欢迎任何建议。

【问题讨论】:

  • 为什么不将聚合作为下一步?
  • 我已经丢失了 $count 中包含的信息,不是吗? 困惑
  • 您可以编写另一个合并函数:merge2 <- function(l, ...) Reduce(function(x, y) merge(x, y, ...), l) 其中l 是数据框或矩阵的列表。我也同意你不需要一步完成所有事情
  • 哦。我明白你指的是什么。也许使用接受不同列的 rbind 函数之一,然后聚合该输出。
  • 您能否添加更多关于您希望如何处理“alpha”和“beta”列的详细信息。不同的data.frames 中是否有不同的列?有些人同时拥有“alpha”和“beta”吗?

标签: r merge dataframe aggregate


【解决方案1】:

以下是我的处理方法:

  1. 为相关的data.frames 创建一个list(就像将它们全部放入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"))

【讨论】:

    【解决方案2】:

    这可以通过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
    

    【讨论】:

    • bind_rows(dfA, dfB, dfC) %&gt;% group_by(ID) %&gt;% summarise_each(funs(sum(.,na.rm=TRUE))) 为您节省了大量打字时间
    • @Khashaa,是的,你知道;一个更干净的电话,当然。我似乎需要在我的_each-fu 中复习一下。谢谢。
    猜你喜欢
    • 2020-04-10
    • 2012-12-15
    • 2023-03-16
    • 2019-02-27
    • 1970-01-01
    • 2020-01-11
    • 2019-08-05
    • 2018-06-13
    • 2016-09-07
    相关资源
    最近更新 更多