【问题标题】:Calculate column sums for each combination of two grouping variables [duplicate]计算两个分组变量的每个组合的列总和[重复]
【发布时间】:2015-09-20 08:35:51
【问题描述】:

我有一个看起来像这样的数据集:

 Type Age   count1  count2  Year   Pop1   Pop2  TypeDescrip
  A   35    1        1      1990   30000  50000  alpha                                 
  A   35    3        1      1990   30000  50000  alpha 
  A   45    2        3      1990   20000  70000  alpha 
  B   45    2        1      1990   20000  70000  beta
  B   45    4        5      1990   20000  70000  beta 

我想在 Type 和 Age 列中添加匹配的行数。所以理想情况下,我最终会得到一个如下所示的数据集:

 Type  Age  count1  count2  Year   Pop1   Pop2  TypeDescrip 
  A   35    4        2      1990   30000  50000  alpha 
  A   45    2        3      1990   20000  70000  alpha 
  B   45    6        6      1990   20000  70000  beta 

我尝试过使用嵌套的duplicated() 语句,如下所示:

typedup = duplicated(df$Type)
bothdup = duplicated(df[(typedup == TRUE),]$Age)

但这会返回年龄或类型重复的索引,不一定是当一行有两个重复时。

我也试过tapply:

tapply(c(df$count1, df$count2), c(df$Age, df$Type), sum)

但是这个输出很难处理。完成后我想要一个 data.frame 。

我不想使用 for 循环,因为我的数据集非常大。

【问题讨论】:

  • 如果您有许多列要分组和求和,请参阅stackoverflow.com/questions/30669817/…
  • @Frank 我认为 必须 是这个问题的副本 - 但我没有找到任何完美的匹配。这个问题有两个分组变量,这使得它与您链接的那个不同。
  • @SamFirke 对我的口味来说差异不够大:) 无论如何,重要的区别不是两个分组变量,而是两列相加。如果只有一个,那么 OP 的 tapply 几乎可以“工作”(至少在给出正确数字的意义上,尽管不在 data.frame 中)。
  • 我认为您的 TypeDescript 将是预期输出中第二行的测试版。试试df2 %>% group_by(Type, Age,Pop1, Pop2, TypeDescrip) %>% summarise_each(funs(sum), matches('^count'))

标签: r aggregate


【解决方案1】:

试试

library(dplyr)
df1 %>%
     group_by(Type, Age) %>% 
     summarise_each(funs(sum))
#    Type Age count1 count2
#1    A  35      4      2
#2    A  45      2      3
#3    B  45      6      6

在较新版本的dplyr

df1 %>%
     group_by(Type, Age) %>%
     summarise_all(sum)

或者使用base R

 aggregate(.~Type+Age, df1, FUN=sum)
 #    Type Age count1 count2
 #1    A  35      4      2
 #2    A  45      2      3
 #3    B  45      6      6

或者

library(data.table)
setDT(df1)[, lapply(.SD, sum), .(Type, Age)] 
#   Type Age count1 count2
#1:    A  35      4      2
#2:    A  45      2      3
#3:    B  45      6      6

更新

基于新的数据集,

 df2 %>%
     group_by(Type, Age,Pop1, Pop2, TypeDescrip) %>% 
     summarise_each(funs(sum), matches('^count'))
 #    Type Age  Pop1  Pop2 TypeDescrip count1 count2
 #1    A  35 30000 50000       alpha      4      2
 #2    A  45 20000 70000        beta      2      3
 #3    B  45 20000 70000        beta      6      6

数据

 df1 <- structure(list(Type = c("A", "A", "A", "B", "B"), Age = c(35L, 
 35L, 45L, 45L, 45L), count1 = c(1L, 3L, 2L, 2L, 4L), count2 = c(1L, 
 1L, 3L, 1L, 5L)), .Names = c("Type", "Age", "count1", "count2"
 ), class = "data.frame", row.names = c(NA, -5L))

 df2 <- structure(list(Type = c("A", "A", "A", "B", "B"), Age = c(35L, 
 35L, 45L, 45L, 45L), count1 = c(1L, 3L, 2L, 2L, 4L), count2 = c(1L, 
 1L, 3L, 1L, 5L), Year = c(1990L, 1990L, 1990L, 1990L, 1990L), 
   Pop1 = c(30000L, 30000L, 20000L, 20000L, 20000L), Pop2 = c(50000L, 
   50000L, 70000L, 70000L, 70000L), TypeDescrip = c("alpha", 
   "alpha", "beta", "beta", "beta")), .Names = c("Type", "Age", 
  "count1", "count2", "Year", "Pop1", "Pop2", "TypeDescrip"),
   class =   "data.frame", row.names = c(NA, -5L))

【讨论】:

  • 我喜欢您提供的 group_by 解决方案,但有没有办法在输出中包含更多列?我的数据集比我在原始帖子中给出的示例更宽。
  • @Hannah 你能用一个模仿你原始数据的例子来更新你的帖子吗?我猜你有其他列而不是你想要得到总和的列。但是,如果您想将这些列保留在摘要中,您将选择哪些值。即最后一个,第一个等..
  • @Hannah 用新数据更新了帖子
  • 在第一个使用funs 剪切的代码已弃用。请改用list
【解决方案2】:

@hannah 你也可以通过 sqldf 包来使用 sql

sqldf("select 
Type,Age,
sum(count1) as sum_count1, 
sum(count2) as sum_count2 
from 
 df 
group by 
Type,Age
")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-19
    • 2019-05-03
    • 1970-01-01
    相关资源
    最近更新 更多