使用 group_by(多个变量)时的 dplyr 问题

Posted

技术标签:

【中文标题】使用 group_by(多个变量)时的 dplyr 问题【英文标题】:dplyr issues when using group_by(multiple variables) 【发布时间】:2014-03-06 08:56:52 【问题描述】:

我想开始使用 dplyr 代替 ddply,但我不知道它是如何工作的(我已阅读文档)。

例如,为什么当我尝试 mutate() 时,“group_by”函数无法正常工作?

看mtcars:

图书馆(汽车)

假设我制作了一个 data.frame,它是 mtcars 的摘要,按“cyl”和“gear”分组:

df1 <- mtcars %.%
            group_by(cyl, gear) %.%
            summarise(
                newvar = sum(wt)
            )

然后说我想进一步总结这个数据框。使用 ddply 会很简单,但是当我尝试使用 dplyr 时,它实际上并不是“分组依据”:

df2 <- df1 %.%
            group_by(cyl) %.%
            mutate(
                newvar2 = newvar + 5
            )

仍然产生未分组的输出:

  cyl gear newvar newvar2
1   6    3  6.675  11.675
2   4    4 19.025  24.025
3   6    4 12.375  17.375
4   6    5  2.770   7.770
5   4    3  2.465   7.465
6   8    3 49.249  54.249
7   4    5  3.653   8.653
8   8    5  6.740  11.740

我的语法有问题吗?


编辑:

如果我用 plyr 和 ddply 来做这个:

df1 <- ddply(mtcars, .(cyl, gear), summarise, newvar = sum(wt))

然后得到第二个df:

df2 <- ddply(df1, .(cyl), summarise, newvar2 = sum(newvar) + 5)

但同样的方法,在 summarise() 函数中使用 sum(newvar) + 5 不适用于 dplyr...

【问题讨论】:

您能给我们提供与ddply 等效的plyr 代码吗? “未分组”是什么意思?你期望每组一排?或者您希望同一组中的所有行都在彼此下方? 我希望第二个 df 只有三行(每个 cyl 一个),因为它看起来与我刚刚在编辑中添加的 ddply 参数......我认为这只是一个问题在我遗漏的地方添加一个论点? 那我觉得你混淆了mutatesummarise 啊,原来如此。如果我想在汇总数据框的同时添加新变量,那么汇总是否会像变异一样有效? 【参考方案1】:

我遇到了类似的问题。我发现只需分离 plyr 即可解决:

detach(package:plyr)    
library(dplyr)

【讨论】:

在过去的一个半小时里一直坐在这里拉头发,试图理解为什么 dplyr 只是忽略了我的分组。很高兴知道我不只是疯了。 我无法弄清楚为什么代码在使用 summarize 时运行良好,但后来访问它时却没有。事实上,我在加载dplyr 后添加了plyr。这就是为什么。不确定它是否是最近添加的,但我最近在加载这两个时发现了这个:You have loaded plyr after dplyr - this is likely to cause problems. If you need functions from both plyr and dplyr, please load plyr first, then dplyr: library(plyr); library(dplyr) 这种情况经常发生在dplyr 方法被重载的情况下。一个通用的解决方案是使用dplyr::summerise(...) 显式引用dplyr 的方法版本。【参考方案2】:

让 Dickoa 的答案更进一步——正如 Hadley 所说,“总结剥离了一层分组”。它从您应用它的相反顺序剥离分组,因此您可以使用

mtcars %>%
 group_by(cyl, gear) %>%
 summarise(newvar = sum(wt)) %>%
 summarise(newvar2 = sum(newvar) + 5)

请注意,如果您在第二行中使用group_by(gear, cyl),这将给出不同的答案。

让你的第一次尝试工作:

df1 <- mtcars %>%
 group_by(cyl, gear) %>%
 summarise(newvar = sum(wt))

df2 <- df1 %>%
 group_by(cyl) %>%
 summarise(newvar2 = sum(newvar)+5)

【讨论】:

我仍然想获得有关哈德利“剥离”隐喻的更好信息。有没有人对此有一些参考或其他已发布的答案? cran.rstudio.com/web/packages/dplyr/vignettes/introduction.html,请参阅包含以下短语的部分:“每个摘要都会剥离一层分组”【参考方案3】:

如果您使用summarise 而不是mutateplyr 代码转换为dplyr,您会得到相同的结果。

library(plyr)
df1 <- ddply(mtcars, .(cyl, gear), summarise, newvar = sum(wt))
df2 <- ddply(df1, .(cyl), summarise, newvar2 = sum(newvar) + 5)
df2
##   cyl newvar2
## 1   4  30.143
## 2   6  26.820
## 3   8  60.989

detach(package:plyr)    
library(dplyr)
mtcars %.%
    group_by(cyl, gear) %.%
    summarise(newvar = sum(wt)) %.%
    group_by(cyl) %.%
    summarise(newvar2 = sum(newvar) + 5)
##   cyl newvar2
## 1   4  30.143
## 2   8  60.989
## 3   6  26.820

编辑

由于summarise 丢弃了最后一组 (gear),您可以跳过第二组 group_by(请参阅下面的 @hadley 评论)

library(dplyr)
mtcars %.%
    group_by(cyl, gear) %.%
    summarise(newvar = sum(wt)) %.%
    summarise(newvar2 = sum(newvar) + 5)
##   cyl newvar2
## 1   4  30.143
## 2   8  60.989
## 3   6  26.820

【讨论】:

所以第二个“group_by()”和“summarise()”调用会覆盖第一个? 是的,你也可以使用regroup 来强制执行。 这里不需要第二个group_by(),因为汇总会自动删除最后一个组(它折叠的组)。 谢谢@hadley 我不知道这个功能。 如果你因为某种原因不想分离plyr,你总是可以在group_bysummarize函数前面指定dplyr::【参考方案4】:

分离plyr 是解决问题的一种方法,因此您可以根据需要使用dplyr 函数...但是如果您需要plyr 中的其他函数来完成代码中的其他任务怎么办?

(在这个例子中,我已经加载了 dplyrplyr 库)

假设我们有一个简单的data.frame,我们想要计算变量value的分组总和,当按gname的不同级别分组时

> dx<-data.frame(gname=c(1,1,1,2,2,2,3,3,3), value = c(2,2,2,4,4,4,5,6,7))
> dx
  gname value
1     1     2
2     1     2
3     1     2
4     2     4
5     2     4
6     2     4
7     3     5
8     3     6
9     3     7

但是当我们尝试使用我们认为会产生dplyr 分组总和时,会发生以下情况:

dx %>% group_by(gname) %>% mutate(mysum=sum(value))
Source: local data frame [9 x 3]
Groups: gname

  gname value mysum
1     1     2    36
2     1     2    36
3     1     2    36
4     2     4    36
5     2     4    36
6     2     4    36
7     3     5    36
8     3     6    36
9     3     7    36

它没有给我们想要的答案。可能是因为group_by 和或mutate 函数在dplyrplyr 之间的某些交互或重载。我们可以分离plyr,但另一种方法是对group_bymutatedplyr 版本进行唯一调用:

dx %>% dplyr::group_by(gname) %>% dplyr::mutate(mysum=sum(value))
Source: local data frame [9 x 3]
Groups: gname

  gname value mysum
1     1     2     6
2     1     2     6
3     1     2     6
4     2     4    12
5     2     4    12
6     2     4    12
7     3     5    18
8     3     6    18
9     3     7    18

现在我们看到它按预期工作。

【讨论】:

【参考方案5】:

dplyr 正在按照您的示例中的预期工作。正如您所指定的那样,变异只会在创建 newvar2 时为 newvar 的每个值添加 5。无论您是否分组,这看起来都一样。但是,如果您指定按组不同的内容,您将得到不同的内容。例如:

df1 %.%
            group_by(cyl) %.%
            mutate(
                newvar2 = newvar + mean(cyl)
            )

【讨论】:

以上是关于使用 group_by(多个变量)时的 dplyr 问题的主要内容,如果未能解决你的问题,请参考以下文章

当我在`dplyr`之后加载`plyr`时,为啥汇总或变异不适用于group_by?

R使用dplyr group_by / sum for循环,作为连接列表输出

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

R语言dplyr包使用group_by函数和summarise函数计算单分类变量分组均值ggplot2可视化线图(line plot)并设置线条类型为虚线(set line types)

R语言dplyr包使用group_by函数和summarise函数计算单分类变量分组均值ggplot2可视化线图(line plot)并设置线条类型为虚线(set line types)

dplyr summarise :在循环中按多个变量分组并将结果添加到同一数据框中