54

我想开始使用 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 ...

4

5 回答 5

77

我有一个类似的问题。我发现简单地分离plyr解决了它:

detach(package:plyr)    
library(dplyr)
于 2014-08-14T16:45:44.203 回答
43

将 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)
于 2014-02-09T07:01:23.517 回答
11

如果您将plyr代码转换为dplyrusingsummarise而不是mutate得到相同的结果。

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
于 2014-02-09T00:28:31.127 回答
6

分离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

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

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

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

于 2015-02-27T02:14:41.463 回答
5

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

df1 %.%
            group_by(cyl) %.%
            mutate(
                newvar2 = newvar + mean(cyl)
            )
于 2014-02-09T00:16:31.260 回答