dplyr:子分组(group_by)数据帧上的colSums:优雅

Posted

技术标签:

【中文标题】dplyr:子分组(group_by)数据帧上的colSums:优雅【英文标题】:dplyr: colSums on sub-grouped (group_by) data frames: elegantly 【发布时间】:2014-07-09 05:16:12 【问题描述】:

我有一个非常大的数据框 (265,874 x 30),包含三个合理的组:年龄类别 (1-6)、日期(5479 个)和地理位置(总共 4 个)。每条记录都由其中的一个选项以及 27 个计数变量组成。我想按每个分组变量进行分组,然后对生成的 27 个子分组变量进行 colSums 。我一直在尝试使用 dplyr (v0.2) 来做到这一点,因为手动完成最终会设置很多冗余的东西(或者诉诸循环来遍历分组选项,因为缺乏优雅的解决方案)。

示例代码

countData <- sample(0:10, 2000, replace = TRUE)
dates <- sample(seq(as.Date("2010/1/1"), as.Date("2010/01/30"), "days"), 200, replace = TRUE)
locality <- sample(1:2, 2000, replace = TRUE)
ageCat <- sample(1:2, 2000, replace = TRUE)
sampleDF <- data.frame(dates, locality, ageCat, matrix(countData, nrow = 200, ncol = 10))

那我想做的是……

library("dplyr")
sampleDF %.% group_by(locality, ageCat, dates) %.% do(colSums(.[, -(1:3)]))

但这并不完全有效,因为 colSums() 的结果不是数据帧。如果我施放它,它会起作用:

sampleDF %.% group_by(locality, ageCat, dates) %.% do(data.frame(matrix(colSums(.[, -(1:3)]), nrow = 1, ncol = 10)))

但最后的 do(...) 位似乎很笨拙。

关于如何更优雅或更有效地做到这一点有什么想法吗?我想问题归结为:如何最好地使用 do() 函数和 .运算符通过 colSums 汇总数据框。

注意:do(.) 运算符仅适用于 dplyr 0.2,因此您需要从 GitHub (link) 获取它,而不是从 CRAN。

编辑:建议的结果

三种解决方案

    我在帖子中的建议:经过,146.765 秒。

    @joran 的建议如下:6.902 秒

    @eddi 在 cmets 中的建议,使用 data.table:6.715 秒。

我没有费心去复制,只是使用了 system.time() 来获得一个粗略的衡量标准。从外观上看,dplyrdata.table 在我的数据集上的性能大致相同,并且在正确使用时两者都比我想出的 hack 解决方案快得多昨天。

【问题讨论】:

您介意分享一个可以下载 dplyr 0.2 的链接吗?我会很感激,因为我没有在 GitHub 上找到下载(它可能会让其他社区成员更容易回答你的问题)。 @beginneR 如果您查看 github 页面上的自述文件,您将看到从 github 安装的命令。 (使用 devtools 包)。 @joran 太棒了,现在正在安装.. 感谢您的提示。 @beginneR 我对 OS X 的 magrittr 依赖有点麻烦,我必须从源代码安装它;由于某种原因,它正在寻找错误版本的二进制文件。 因为您的问题专门针对dplyr,所以我将其作为评论 - 这里的语法不那么笨拙(并且可能更快):dt = as.data.table(sampleDF); dt[, lapply(.SD, sum), by = list(locality, ageCat, dates)] 【参考方案1】:

除非我遗漏了什么,否则这似乎是 summarise_each 的工作(类似于 plyrcolwise 类似物):

sampleDF %.% group_by(locality, ageCat, dates) %.% summarise_each(funs(sum))

默认情况下,汇总函数中不包含分组列,您可以只选择列的子集来应用函数,使用与使用select时相同的技术。

(据我所知,summarise_eachdplyr 的 0.2 版中,但不在 0.1.3 版中。)

【讨论】:

我错过了 summarise_each:感谢您的建议!正如我对原始帖子的编辑所显示的那样,它比重复投射要快得多。【参考方案2】:

2014 年的 joran's answer 中提到的方法 summarise_each 已被弃用。

请改用summarize_all()summarize_at()

【讨论】:

【参考方案3】:

从 2018 年开始,Hack-R's answer 中提到的 summarize_allsummarize_at 方法已被取代。

请改用summarize()/summarise()across()

【讨论】:

以上是关于dplyr:子分组(group_by)数据帧上的colSums:优雅的主要内容,如果未能解决你的问题,请参考以下文章

R语言使用dplyr包聚合(group_by)数据并过滤(fiter)之后再拆开聚合数据(ungroup取消组合)使用ggplot2可视化拆开分组后的线图(line plot)

R语言dplyr包使用arrange函数group_by函数mutate函数生成分组数据的排名(rank)实战(Rank Variable by Group):升序排名降序排名以及相同排名的处理

将 dplyr 函数 group_by() 与 cut() 一起使用

R语言dplyr包获取dataframe分组聚合汇总统计值实战(group_by() and summarize() ):均值中位数分位数IQRMADcountunique

R语言dplyr包使用group_by函数arrange函数和filter函数获取每个分组的第一个第N个最后一个记录实战

如何根据过滤条件添加计数列而不是在dplyr中进行分组?