汇总/汇总每组的多个变量(例如总和,平均值)

Mik*_*eTP 143 aggregate r dataframe r-faq data.table

从数据帧,是否有聚集(一个简单的方法sum,mean,max同时等c)中多个变量?

以下是一些示例数据:

library(lubridate)
days = 365*2
date = seq(as.Date("2000-01-01"), length = days, by = "day")
year = year(date)
month = month(date)
x1 = cumsum(rnorm(days, 0.05)) 
x2 = cumsum(rnorm(days, 0.05))
df1 = data.frame(date, year, month, x1, x2)
Run Code Online (Sandbox Code Playgroud)

我想同时按年和月汇总数据框中的变量x1x2变量df2.以下代码聚合x1变量,但是是否也可以同时聚合x2变量?

### aggregate variables by year month
df2=aggregate(x1 ~ year+month, data=df1, sum, na.rm=TRUE)
head(df2)
Run Code Online (Sandbox Code Playgroud)

任何建议将不胜感激.

And*_*rie 181

是的,在你的formula,你可以cbind聚合数字变量:

aggregate(cbind(x1, x2) ~ year + month, data = df1, sum, na.rm = TRUE)
   year month         x1          x2
1  2000     1   7.862002   -7.469298
2  2001     1 276.758209  474.384252
3  2000     2  13.122369 -128.122613
...
23 2000    12  63.436507  449.794454
24 2001    12 999.472226  922.726589
Run Code Online (Sandbox Code Playgroud)

?aggregateformula论点和例子.

  • 值得注意的是,当cbind中的任何变量具有NA时,将为cbind中的每个变量删除该行.这不是我期待的行为. (12认同)
  • @ClockSlave,那么你需要在LHS上使用`.`.`aggregate(.〜year + month,df1,sum,na.rm = TRUE)`.在这个例子中,"date"的"sum"虽然没有意义.... (7认同)
  • 如果我不想要两个变量而是两个函数怎么办?例如mean和sd. (4认同)
  • cbind可以使用动态变量吗? (3认同)
  • 如果我想使用所有剩余的变量(年、月除外)而不是 x1 和 x2,该怎么办 (2认同)

小智 48

使用data.table快速的包(对于较大的数据集很有用)

https://github.com/Rdatatable/data.table/wiki

library(data.table)
df2 <- setDT(df1)[, lapply(.SD, sum), by=.(year, month), .SDcols=c("x1","x2")]
setDF(df2) # convert back to dataframe
Run Code Online (Sandbox Code Playgroud)

使用plyr包

require(plyr)
df2 <- ddply(df1, c("year", "month"), function(x) colSums(x[c("x1", "x2")]))
Run Code Online (Sandbox Code Playgroud)

使用Hmisc包中的summarize()(虽然我的例子中列标题很乱)

# need to detach plyr because plyr and Hmisc both have a summarize()
detach(package:plyr)
require(Hmisc)
df2 <- with(df1, summarize( cbind(x1, x2), by=llist(year, month), FUN=colSums))
Run Code Online (Sandbox Code Playgroud)


Jaa*_*aap 46

随着dplyr包,您可以使用summarise_all,summarise_atsummarise_if功能,同时聚合多个变量.对于示例数据集,您可以按如下方式执行此操作:

library(dplyr)
# summarising all non-grouping variables
df2 <- df1 %>% group_by(year, month) %>% summarise_all(sum)

# summarising a specific set of non-grouping variables
df2 <- df1 %>% group_by(year, month) %>% summarise_at(vars(x1, x2), sum)
df2 <- df1 %>% group_by(year, month) %>% summarise_at(vars(-date), sum)

# summarising a specific set of non-grouping variables using select_helpers
# see ?select_helpers for more options
df2 <- df1 %>% group_by(year, month) %>% summarise_at(vars(starts_with('x')), sum)
df2 <- df1 %>% group_by(year, month) %>% summarise_at(vars(matches('.*[0-9]')), sum)

# summarising a specific set of non-grouping variables based on condition (class)
df2 <- df1 %>% group_by(year, month) %>% summarise_if(is.numeric, sum)
Run Code Online (Sandbox Code Playgroud)

后两种选择的结果:

    year month        x1         x2
   <dbl> <dbl>     <dbl>      <dbl>
1   2000     1 -73.58134  -92.78595
2   2000     2 -57.81334 -152.36983
3   2000     3 122.68758  153.55243
4   2000     4 450.24980  285.56374
5   2000     5 678.37867  384.42888
6   2000     6 792.68696  530.28694
7   2000     7 908.58795  452.31222
8   2000     8 710.69928  719.35225
9   2000     9 725.06079  914.93687
10  2000    10 770.60304  863.39337
# ... with 14 more rows
Run Code Online (Sandbox Code Playgroud)

注意:summarise_each不赞成使用summarise_all,summarise_atsummarise_if.


正如上面的评论中所提到的,您也可以使用-package中的recast函数reshape2:

library(reshape2)
recast(df1, year + month ~ variable, sum, id.var = c("date", "year", "month"))
Run Code Online (Sandbox Code Playgroud)

这将给你相同的结果.


EDi*_*EDi 44

这个year()功能来自哪里?

您还可以使用该reshape2包执行此任务:

require(reshape2)
df_melt <- melt(df1, id = c("date", "year", "month"))
dcast(df_melt, year + month ~ variable, sum)
#  year month         x1           x2
1  2000     1  -80.83405 -224.9540159
2  2000     2 -223.76331 -288.2418017
3  2000     3 -188.83930 -481.5601913
4  2000     4 -197.47797 -473.7137420
5  2000     5 -259.07928 -372.4563522
Run Code Online (Sandbox Code Playgroud)

  • `recast`函数(也来自`reshape2`)一次性集成了`melt`和`dcast`函数,用于这样的任务:`recast(df1,year + month~variable,sum,id.var = c("日期","年","月"))` (6认同)

akr*_*run 8

使用dplyr版本 >= 1.0.0,我们还可以使用summarise在多列上应用函数across

\n
library(dplyr)\ndf1 %>% \n    group_by(year, month) %>%\n    summarise(across(starts_with('x'), sum))\n# A tibble: 24 x 4\n# Groups:   year [2]\n#    year month     x1     x2\n#   <dbl> <dbl>  <dbl>  <dbl>\n# 1  2000     1   11.7  52.9 \n# 2  2000     2  -74.1 126.  \n# 3  2000     3 -132.  149.  \n# 4  2000     4 -130.    4.12\n# 5  2000     5  -91.6 -55.9 \n# 6  2000     6  179.   73.7 \n# 7  2000     7   95.0 409.  \n# 8  2000     8  255.  283.  \n# 9  2000     9  489.  331.  \n#10  2000    10  719.  305.  \n# \xe2\x80\xa6 with 14 more rows\n
Run Code Online (Sandbox Code Playgroud)\n


Joz*_*zef 6

有趣的是,此处未展示base R aggregatedata.frame方法,而是在公式接口上方使用,因此出于完整性考虑:

aggregate(
  x = df1[c("x1", "x2")],
  by = df1[c("year", "month")],
  FUN = sum, na.rm = TRUE
)
Run Code Online (Sandbox Code Playgroud)

聚合的data.frame方法的更通用用法:

由于我们提供了

  • data.frame作为x
  • a listdata.frame也是a list)as by,如果我们需要以动态方式使用它(例如,使用其他列进行聚合和通过进行聚合)非常简单,这将非常有用
  • 还具有定制的聚合功能

例如这样:

colsToAggregate <- c("x1")
aggregateBy <- c("year", "month")
dummyaggfun <- function(v, na.rm = TRUE) {
  c(sum = sum(v, na.rm = na.rm), mean = mean(v, na.rm = na.rm))
}

aggregate(df1[colsToAggregate], by = df1[aggregateBy], FUN = dummyaggfun)
Run Code Online (Sandbox Code Playgroud)

  • 首先,这是一个被严重低估的答案,谢谢。其次,您认为是否可以生成一个“聚合”函数来计算给定变量集的“平均值”和另一组变量的“总和”?我真的很好奇它,它可以节省我很多时间。再次感谢。 (3认同)