使用 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 参数......我认为这只是一个问题在我遗漏的地方添加一个论点?
那我觉得你混淆了mutate
和summarise
。
啊,原来如此。如果我想在汇总数据框的同时添加新变量,那么汇总是否会像变异一样有效?
【参考方案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
而不是mutate
将plyr
代码转换为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_by
和summarize
函数前面指定dplyr::
。【参考方案4】:
分离plyr
是解决问题的一种方法,因此您可以根据需要使用dplyr
函数...但是如果您需要plyr
中的其他函数来完成代码中的其他任务怎么办?
(在这个例子中,我已经加载了 dplyr
和 plyr
库)
假设我们有一个简单的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
函数在dplyr
和plyr
之间的某些交互或重载。我们可以分离plyr
,但另一种方法是对group_by
和mutate
的dplyr
版本进行唯一调用:
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)