web-dev-qa-db-fra.com

Variable de classement par groupe (dplyr)

J'ai une trame de données avec des colonnes x1, x2, group et je voudrais générer une nouvelle trame de données avec une colonne supplémentaire rank qui indique l'ordre de x1 dans son groupe.

Il y a une question connexe ici , mais la réponse acceptée ne semble plus fonctionner.

Jusqu'ici, ça va:

library(dplyr)
data(iris)
by_species <- iris %>% 
              arrange(Species, Sepal.Length) %>% 
              group_by(Species)  

Mais quand j'essaye d'obtenir les rangs par groupe:

by_species <- mutate(by_species, rank=row_number())

L'erreur est:

Erreur de classement (x, ties.method = "first", na.last = "keep"):
L'argument "x" est manquant, sans valeur par défaut

Mise à jour

Le problème était un conflit entre dplyr et plyr. Pour reproduire l'erreur, chargez les deux packages:

library(dplyr)
library(plyr)
data(iris)
by_species <- iris %>% 
              arrange(Species, Sepal.Length) %>% 
              group_by(Species) %>% 
              mutate(rank=row_number())
# Error in rank(x, ties.method = "first", na.last = "keep") : 
# argument "x" is missing, with no default

Déchargement plyr cela fonctionne comme il se doit:

detach("package:plyr", unload=TRUE)
by_species <- iris %>% 
              arrange(Species, Sepal.Length) %>% 
              group_by(Species) %>% 
              mutate(rank=row_number())

by_species %>% filter(rank <= 3)

##   Sepal.Length Sepal.Width Petal.Length Petal.Width    Species  rank
##          (dbl)       (dbl)        (dbl)       (dbl)     (fctr) (int)
## 1          4.3         3.0          1.1         0.1     setosa     1
## 2          4.4         2.9          1.4         0.2     setosa     2
## 3          4.4         3.0          1.3         0.2     setosa     3
## 4          4.9         2.4          3.3         1.0 versicolor     1
## 5          5.0         2.0          3.5         1.0 versicolor     2
## 6          5.0         2.3          3.3         1.0 versicolor     3
## 7          4.9         2.5          4.5         1.7  virginica     1
## 8          5.6         2.8          4.9         2.0  virginica     2
## 9          5.7         2.5          5.0         2.0  virginica     3
17
alberto

Ce qui suit produit le résultat souhaité comme spécifié.

library(dplyr)

by_species <- iris %>% arrange(Species, Sepal.Length) %>%
    group_by(Species) %>% 
    mutate(rank = rank(Sepal.Length, ties.method = "first"))

by_species %>% filter(rank <= 3)
##Source: local data frame [9 x 6]
##Groups: Species [3]
##
##  Sepal.Length Sepal.Width Petal.Length Petal.Width    Species  rank
##         (dbl)       (dbl)        (dbl)       (dbl)     (fctr) (int)
##1          4.3         3.0          1.1         0.1     setosa     1
##2          4.4         2.9          1.4         0.2     setosa     2
##3          4.4         3.0          1.3         0.2     setosa     3
##4          4.9         2.4          3.3         1.0 versicolor     1
##5          5.0         2.0          3.5         1.0 versicolor     2
##6          5.0         2.3          3.3         1.0 versicolor     3
##7          4.9         2.5          4.5         1.7  virginica     1
##8          5.6         2.8          4.9         2.0  virginica     2
##9          5.7         2.5          5.0         2.0  virginica     3

by_species %>% slice(1:3)
##Source: local data frame [9 x 6]
##Groups: Species [3]
##
##  Sepal.Length Sepal.Width Petal.Length Petal.Width    Species  rank
##         (dbl)       (dbl)        (dbl)       (dbl)     (fctr) (int)
##1          4.3         3.0          1.1         0.1     setosa     1
##2          4.4         2.9          1.4         0.2     setosa     2
##3          4.4         3.0          1.3         0.2     setosa     3
##4          4.9         2.4          3.3         1.0 versicolor     1
##5          5.0         2.0          3.5         1.0 versicolor     2
##6          5.0         2.3          3.3         1.0 versicolor     3
##7          4.9         2.5          4.5         1.7  virginica     1
##8          5.6         2.8          4.9         2.0  virginica     2
##9          5.7         2.5          5.0         2.0  virginica     3
22
steveb

Pour les futurs lecteurs, la variable de classement par groupe peut être obtenue en utilisant la base R. Selon l'exemple de données iris du PO pour classer selon Sepal.Length:

# ORDER BY SPECIES AND SEPAL.LENGTH
iris <- iris[with(iris, order(Species, Sepal.Length)), ]

# RUN A ROW COUNT FOR RANK BY SPECIES GROUP
iris$rank <- sapply(1:nrow(iris), 
                    function(i) sum(iris[1:i, c('Species')]==iris$Species[i]))

# FILTER DATA FRAME BY TOP 3
iris <- iris[iris$rank <= 3,]
2
Parfait