web-dev-qa-db-fra.com

Problèmes liés à dplyr lors de l'utilisation de group_by (plusieurs variables)

Je veux commencer à utiliser dplyr à la place de ddply mais je ne peux pas comprendre comment cela fonctionne (j'ai lu la documentation).

Par exemple, pourquoi quand j'essaie de muter () quelque chose, la fonction "group_by" ne fonctionne-t-elle pas comme prévu?

En regardant mtcars:

bibliothèque (voiture)

Dites que je fais un data.frame qui est un résumé de mtcars, regroupés par "cyl" et "gear":

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

Ensuite, disons que je veux résumer davantage cette base de données. Avec ddply, ce serait simple, mais lorsque j'essaie de le faire avec dplyr, ce n'est pas réellement "grouper par":

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

Est-ce que je fais quelque chose de mal avec la syntaxe?


Modifier:

Si je devais le faire avec plyr and ddply:

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

et ensuite pour obtenir le deuxième df:

df2 <- ddply(df1, .(cyl), summarise, newvar2 = sum(newvar) + 5)

Mais cette même approche, avec sum (newvar) + 5 dans la fonction resume (), ne fonctionne pas avec dplyr ...

45
Marc Tulla

Prenant la réponse de Dickoa un peu plus loin - comme le dit Hadley, "résumez les pelures d'une seule couche de groupement". Il se détache du regroupement à partir de l’ordre inverse dans lequel vous l’avez appliqué afin que vous puissiez simplement utiliser

mtcars %>%
 group_by(cyl, gear) %>%
 summarise(newvar = sum(wt)) %>%
 summarise(newvar2 = sum(newvar) + 5)

Notez que cela donnera une réponse différente si vous utilisez group_by(gear, cyl) à la deuxième ligne.

Et pour réussir votre première tentative:

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

df2 <- df1 %>%
 group_by(cyl) %>%
 summarise(newvar2 = sum(newvar)+5)
40
Tim Cameron

J'avais un problème similaire. J'ai découvert que le simple détachement de plyr le résolvait:

detach(package:plyr)    
library(dplyr)
64
ManneR

Si vous traduisez votre code plyr en dplyr à l'aide de 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

Puisque summarise supprime le dernier groupe (gear), vous pouvez ignorer le second group_by _ (voir le commentaire @hadley 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
11
dickoa

Détacher plyr est un moyen de résoudre le problème afin que vous puissiez utiliser les fonctions dplyr à votre guise ... mais si vous avez besoin d'autres fonctions de plyr pour effectuer d'autres tâches code?

(Dans cet exemple, les bibliothèques dplyr et plyr sont chargées)

Supposons que nous ayons un simple data.frame et que nous voulions calculer la somme groupe de la variable value, lorsque regroupé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 lorsque nous essayons d'utiliser ce que nous pensons générer une somme groupée de dplyr, 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

Cela ne nous donne pas la réponse souhaitée. Probablement à cause d'une interaction ou d'une surcharge du group_by et ou mutate fonctions entre dplyr et plyr. Nous pourrions détacher plyr, mais vous pouvez également appeler les versions dplyr 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

nous voyons maintenant que cela fonctionne comme prévu.

6
Brett Borghetti

dplyr fonctionne comme prévu dans votre exemple. Mutate, comme vous l'avez spécifié, ajoutera simplement 5 à chaque valeur de newvar lors de la création de newvar2. Cela ressemblerait si vous groupiez ou non. Si, toutefois, vous spécifiez quelque chose qui diffère d'un groupe à l'autre, vous obtiendrez quelque chose de différent. Par exemple:

df1 %.%
            group_by(cyl) %.%
            mutate(
                newvar2 = newvar + mean(cyl)
            )
5
Vincent