problèmes dplyr lors de l'utilisation de group by (variables multiples)
je veux commencer à utiliser dplyr à la place de ddply mais je n'arrive pas à savoir comment ça marche (j'ai lu la documentation).
par exemple, pourquoi quand j'essaie de muter () quelque chose fait que la fonction "group_by" ne fonctionne pas comme il est supposé le faire?
en regardant mtcars:
library (car)
supposons que je fasse une donnée.cadre, qui est un résumé de mtcars, regroupés par "cyl" et "équipement":
df1 <- mtcars %.%
group_by(cyl, gear) %.%
summarise(
newvar = sum(wt)
)
Puis dire que je veux plus de résumer cette dataframe. Avec ddply, ce serait simple, mais quand j'essaie de faire avec avec dplyr, ce n'est pas vraiment "regroupement":
df2 <- df1 %.%
group_by(cyl) %.%
mutate(
newvar2 = newvar + 5
)
donne toujours une sortie non groupée:
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
je fais quelque chose de mal avec la syntaxe?
Edit:
Si je devais le faire avec plyr et ddply:
df1 <- ddply(mtcars, .(cyl, gear), summarise, newvar = sum(wt))
et puis, pour obtenir le deuxième df:
df2 <- ddply(df1, .(cyl), summarise, newvar2 = sum(newvar) + 5)
mais cette même approche, avec somme (newvar) + 5 dans le résumer() ne fonctionne pas avec dplyr...
5 réponses
poussant la réponse de Dickoa un peu plus loin -- comme Hadley le dit "résumez les pelures d'une seule couche de groupage". Il décolle de groupement dans l'ordre inverse dans lequel vous avez appliqué de sorte que vous pouvez simplement utiliser
mtcars %>%
group_by(cyl, gear) %>%
summarise(newvar = sum(wt)) %>%
summarise(newvar2 = sum(newvar) + 5)
Notez que cela vous donnera une réponse différente si vous utilisez group_by(gear, cyl)
dans la deuxième ligne.
Et pour obtenir votre première tentative de travail:
df1 <- mtcars %>%
group_by(cyl, gear) %>%
summarise(newvar = sum(wt))
df2 <- df1 %>%
group_by(cyl) %>%
summarise(newvar2 = sum(newvar)+5)
j'ai eu un problème similaire. J'ai trouvé que tout simplement détacher plyr
résolu:
detach(package:plyr)
library(dplyr)
Si vous traduisez votre plyr
code en dplyr
en utilisant summarise
au lieu de mutate
vous obtenez les mêmes résultats.
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
EDIT
Depuis summarise
supprime le dernier groupe (gear
), vous pouvez ignorer la deuxième group_by
(voir @hadley commentaire ci-dessous)
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
Détacher plyr
est une façon de résoudre le problème donc vous pouvez utiliser dplyr
fonctionne comme souhaité... mais que faire si vous avez besoin d'autres fonctions plyr
pour effectuer d'autres tâches dans votre code?
(Dans cet exemple, j'ai deux dplyr
et plyr
bibliothèques chargés)
supposons que nous ayons une simple donnée.frame et nous voulons calculer la somme groupwise de la variable value
, groupés par différents niveaux 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
Mais quand nous essayons d'utiliser ce que nous croyons va produire un dplyr
regroupés en somme, voici ce qui se passe:
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
il ne nous donne pas la réponse désirée. Probablement à cause d'une interaction ou d'une surcharge de group_by
et ou mutate
fonctions entre dplyr
et plyr
. On pourrait se détacher plyr
, mais une autre façon est de donner un unique appel à dplyr
versions de group_by
et 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
maintenant, nous voyons que cela fonctionne comme prévu.
dplyr fonctionne comme vous devriez vous y attendre dans votre exemple. Muter, comme vous l'avez spécifié, ajoutera juste 5 à chaque valeur de newvar comme il crée newvar2. Cela ressemblerait à la même chose si vous groupez ou non. Si, toutefois, vous spécifiez quelque chose qui diffère par groupe, vous obtiendrez quelque chose de différent. Par exemple:
df1 %.%
group_by(cyl) %.%
mutate(
newvar2 = newvar + mean(cyl)
)