questões dplyr ao usar o grupo por (múltiplas variáveis)

quero começar a usar dplyr em vez de ddply, mas não consigo perceber como funciona (li A documentação).

por exemplo, porque é que quando tento mutar() alguma coisa a função group_by não funciona como é suposto?

olhando para mtcars:

Biblioteca (car) Digamos que faço um dado.quadro que é um resumo dos mtcars, agrupados por "cyl"e " gear":

df1 <- mtcars %.%
            group_by(cyl, gear) %.%
            summarise(
                newvar = sum(wt)
            )
Então diz - me que quero resumir este nome de dados. Com ddply, seria simples, mas quando tento lidar com o dplyr, não é "agrupamento por":

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

Ainda dá uma saída não reunida:

  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
Estou a fazer algo de errado com a sintaxe?


Editar:

Se eu fizesse isto com plyr e ddply:

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

e depois para obter o segundo df:

df2 <- ddply(df1, .(cyl), summarise, newvar2 = sum(newvar) + 5)
[[6]} mas essa mesma abordagem, com sum (newvar) + 5 na função summarise () não funciona com dplyr...

Author: smci, 2014-02-09

5 answers

Levando a resposta de Dickoa um passo mais longe -- como Hadley diz "sumarize peels off a single layer of grouping". Retira o agrupamento da ordem inversa em que o aplicou para poder usar
mtcars %>%
 group_by(cyl, gear) %>%
 summarise(newvar = sum(wt)) %>%
 summarise(newvar2 = sum(newvar) + 5)

Note que isto dará uma resposta diferente se você usar group_by(gear, cyl) na segunda linha.

E para que a tua primeira tentativa funcione:

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

df2 <- df1 %>%
 group_by(cyl) %>%
 summarise(newvar2 = sum(newvar)+5)
 35
Author: Tim Cameron, 2016-11-28 22:07:40
Tive um problema semelhante. Descobri que a simples separação plyr resolveu-se:
detach(package:plyr)    
library(dplyr)
 61
Author: ManneR, 2014-09-08 19:29:34

Se traduzir o seu código plyr para dplyr usando summarise em vez de mutate, obtém os mesmos resultados.

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

EDITAR

Desde que summarise abandona o último grupo (gear), poderá saltar o segundo group_by (veja o comentário de @ hadley abaixo)

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
 10
Author: dickoa, 2014-02-09 21:28:48

Desligar plyr é uma forma de resolver o problema para que possa usar as funções dplyr como desejar... mas e se você precisar de outras funções de plyr para completar outras tarefas em seu código?

(Neste exemplo, eu tenho as bibliotecas dplyr e plyr carregadas)

Suponha que temos dados simples.frame e queremos calcular a soma groupwise da variável value, quando agrupada por diferentes níveis de 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
Mas quando tentarmos usar o que acreditamos produzir uma soma agrupada, eis o que acontece:
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
Não nos dá a resposta desejada. Provavelmente devido a alguma interacção ou sobrecarga das funções group_by e mutate entre dplyr e plyr. Podíamos separar-nos, mas outra maneira é dar um chamamento único às versões de {[[4]} e mutate:
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
Agora vemos que isto funciona como esperado.
 5
Author: Brett Borghetti, 2015-02-27 02:14:41

O Dplyr está a funcionar como deve esperar no seu exemplo. Mutate, como você especificou, irá apenas adicionar 5 para cada valor de newvar, uma vez que cria newvar2. Isto pareceria o mesmo se você agrupar ou não. Se, no entanto, você especificar algo que difere por grupo você vai obter algo diferente. Por exemplo:

df1 %.%
            group_by(cyl) %.%
            mutate(
                newvar2 = newvar + mean(cyl)
            )
 4
Author: Vincent, 2014-02-09 00:16:31