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...
5 answers
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)
plyr
resolveu-se:
detach(package:plyr)
library(dplyr)
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
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)
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.
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)
)