web-dev-qa-db-fra.com

mutate_each / summary_each dans dplyr: comment sélectionner certaines colonnes et donner de nouveaux noms aux colonnes mutées?

Je suis un peu confus à propos du dplyr verbe mutate_each.

Il est assez simple d'utiliser la base mutate de base pour transformer une colonne de données en, par exemple, des scores z, et créer une nouvelle colonne dans votre data.frame (ici avec le nom z_score_data):

newDF <- DF %>%
  select(one_column) %>%
  mutate(z_score_data = one_column - (mean(one_column) / sd(one_column))

Cependant, comme j'ai beaucoup de colonnes de données que j'aimerais transformer, il semble que je devrais probablement utiliser le mutate_each verbe.

newDF <- DF %>%
     mutate_each(funs(scale))

Jusqu'ici tout va bien. Mais pour l'instant je n'ai pas été capable de comprendre:

  1. Comment puis-je donner à ces nouvelles colonnes des noms appropriés, comme je le peux dans mutate?
  2. Comment puis-je sélectionner certaines colonnes que je souhaite muter, comme ce fut le cas avec select dans le premier cas?

Merci de votre aide.

59
Matt O'Brien

Mise à jour pour dplyr> = 0.4.3.9000

Dans la version de développement de dplyr 0.4.3.9000 (au moment de l'écriture), nommer à l'intérieur de mutate_each Et summarise_each A été simplifié comme indiqué dans le News :

Le comportement de nommage de summarise_each() et mutate_each() a été modifié afin de pouvoir forcer l'inclusion de la fonction et du nom de la variable: summarise_each(mtcars, funs(mean = mean), everything())

Ceci est principalement important si vous souhaitez appliquer une seule fonction dans mutate_each/summarise_each Et que vous souhaitez attribuer de nouveaux noms à cette colonne.

Pour montrer la différence, voici la sortie de dplyr 0.4.3.9000 utilisant la nouvelle fonctionnalité de nommage, contrairement à l'option a.2 ci-dessous:

library(dplyr) # >= 0.4.3.9000
iris %>% mutate_each(funs(mysum = sum(.)), -Species) %>% head()
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length_mysum Sepal.Width_mysum
#1          5.1         3.5          1.4         0.2  setosa              876.5             458.6
#2          4.9         3.0          1.4         0.2  setosa              876.5             458.6
#3          4.7         3.2          1.3         0.2  setosa              876.5             458.6
#4          4.6         3.1          1.5         0.2  setosa              876.5             458.6
#5          5.0         3.6          1.4         0.2  setosa              876.5             458.6
#6          5.4         3.9          1.7         0.4  setosa              876.5             458.6
#  Petal.Length_mysum Petal.Width_mysum
#1              563.7             179.9
#2              563.7             179.9
#3              563.7             179.9
#4              563.7             179.9
#5              563.7             179.9
#6              563.7             179.9

Si vous ne fournissez pas de nouveaux noms et que vous ne fournissez qu'une seule fonction, dplyr modifiera les colonnes existantes (comme dans les versions précédentes):

iris %>% mutate_each(funs(sum), -Species) %>% head()
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#1        876.5       458.6        563.7       179.9  setosa
#2        876.5       458.6        563.7       179.9  setosa
#3        876.5       458.6        563.7       179.9  setosa
#4        876.5       458.6        563.7       179.9  setosa
#5        876.5       458.6        563.7       179.9  setosa
#6        876.5       458.6        563.7       179.9  setosa

Je suppose que cette nouvelle fonctionnalité sera disponible via CRAN dans la prochaine version 0.4.4.


versions de dplyr <= 0.4.3:

Comment puis-je donner à ces nouvelles colonnes des noms appropriés, comme je peux le faire pour muter?

a) 1 fonction appliquée dans mutate_each/summarise_each

Si vous n'appliquez qu'une fonction à l'intérieur de mutate_each Ou summarise_each, Les colonnes existantes seront transformées et les noms seront conservés tels qu'ils étaient, à moins que vous ne fournissiez un vecteur nommé. à mutate_each_/summarise_each_ (voir option a.4)

Voici quelques exemples:

a.1 seulement 1 fonction -> conservera les noms existants

iris %>% mutate_each(funs(sum), -Species) %>% head()
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#1          876         459          564         180  setosa
#2          876         459          564         180  setosa
#3          876         459          564         180  setosa
#4          876         459          564         180  setosa
#5          876         459          564         180  setosa
#6          876         459          564         180  setosa

a.2 également si vous spécifiez une nouvelle extension de nom de colonne:

iris %>% mutate_each(funs(mysum = sum(.)), -Species) %>% head()
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#1          876         459          564         180  setosa
#2          876         459          564         180  setosa
#3          876         459          564         180  setosa
#4          876         459          564         180  setosa
#5          876         459          564         180  setosa
#6          876         459          564         180  setosa

a.3 Spécifiez manuellement un nouveau nom par colonne (mais uniquement pratique pour quelques colonnes):

iris %>% mutate_each(funs(sum), SLsum = Sepal.Length,SWsum = Sepal.Width,  -Species) %>% head()
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species SLsum SWsum
#1          5.1         3.5          1.4         0.2  setosa   876   459
#2          4.9         3.0          1.4         0.2  setosa   876   459
#3          4.7         3.2          1.3         0.2  setosa   876   459
#4          4.6         3.1          1.5         0.2  setosa   876   459
#5          5.0         3.6          1.4         0.2  setosa   876   459
#6          5.4         3.9          1.7         0.4  setosa   876   459

a.4 Utilisez un vecteur nommé pour créer des colonnes supplémentaires avec de nouveaux noms:

cas 1: conserve les colonnes d'origine

Contrairement aux options a.1, a.2 et a.3, dplyr conservera les colonnes existantes inchangées et créera de nouvelles colonnes dans cette approche. Les noms des nouvelles colonnes sont identiques à ceux du vecteur nommé que vous avez créé à l’avance (vars dans ce cas).

vars <- names(iris)[1:2]  # choose which columns should be mutated
vars <- setNames(vars, paste0(vars, "_sum")) # create new column names
iris %>% mutate_each_(funs(sum), vars) %>% head 
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length_sum Sepal.Width_sum
#1          5.1         3.5          1.4         0.2  setosa            876.5           458.6
#2          4.9         3.0          1.4         0.2  setosa            876.5           458.6
#3          4.7         3.2          1.3         0.2  setosa            876.5           458.6
#4          4.6         3.1          1.5         0.2  setosa            876.5           458.6
#5          5.0         3.6          1.4         0.2  setosa            876.5           458.6
#6          5.4         3.9          1.7         0.4  setosa            876.5           458.6

cas 2: supprimer les colonnes d'origine

Comme vous pouvez le constater, cette approche maintient les colonnes existantes inchangées et ajoute de nouvelles colonnes avec des noms spécifiés. Si vous ne souhaitez pas conserver les colonnes d'origine, mais uniquement les colonnes nouvellement créées (et les autres colonnes), vous pouvez simplement ajouter une instruction select par la suite:

iris %>% mutate_each_(funs(sum), vars) %>% select(-one_of(vars)) %>% head
#  Petal.Length Petal.Width Species Sepal.Length_sum Sepal.Width_sum
#1          1.4         0.2  setosa            876.5           458.6
#2          1.4         0.2  setosa            876.5           458.6
#3          1.3         0.2  setosa            876.5           458.6
#4          1.5         0.2  setosa            876.5           458.6
#5          1.4         0.2  setosa            876.5           458.6
#6          1.7         0.4  setosa            876.5           458.6

b) plus d'une fonction appliquée dans mutate_each/summarise_each

b.1 Laisser dplyr trouver de nouveaux noms

Si vous avez appliqué plus d'une fonction, vous pouvez laisser dplyr déterminer lui-même les noms (et conserver les colonnes existantes):

iris %>% mutate_each(funs(sum, mean), -Species) %>% head()
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length_sum Sepal.Width_sum Petal.Length_sum
#1          5.1         3.5          1.4         0.2  setosa              876             459              564
#2          4.9         3.0          1.4         0.2  setosa              876             459              564
#3          4.7         3.2          1.3         0.2  setosa              876             459              564
#4          4.6         3.1          1.5         0.2  setosa              876             459              564
#5          5.0         3.6          1.4         0.2  setosa              876             459              564
#6          5.4         3.9          1.7         0.4  setosa              876             459              564
#  Petal.Width_sum Sepal.Length_mean Sepal.Width_mean Petal.Length_mean Petal.Width_mean
#1             180              5.84             3.06              3.76              1.2
#2             180              5.84             3.06              3.76              1.2
#3             180              5.84             3.06              3.76              1.2
#4             180              5.84             3.06              3.76              1.2
#5             180              5.84             3.06              3.76              1.2
#6             180              5.84             3.06              3.76              1.2

b.2 Spécifier manuellement les nouveaux noms de colonne

Une autre option, lorsque vous utilisez plus d'une fonction, consiste à spécifier vous-même l'extension du nom de la colonne:

iris %>% mutate_each(funs(MySum = sum(.), MyMean = mean(.)), -Species) %>% head()
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length_MySum Sepal.Width_MySum Petal.Length_MySum
#1          5.1         3.5          1.4         0.2  setosa                876               459                564
#2          4.9         3.0          1.4         0.2  setosa                876               459                564
#3          4.7         3.2          1.3         0.2  setosa                876               459                564
#4          4.6         3.1          1.5         0.2  setosa                876               459                564
#5          5.0         3.6          1.4         0.2  setosa                876               459                564
#6          5.4         3.9          1.7         0.4  setosa                876               459                564
#  Petal.Width_MySum Sepal.Length_MyMean Sepal.Width_MyMean Petal.Length_MyMean Petal.Width_MyMean
#1               180                5.84               3.06                3.76                1.2
#2               180                5.84               3.06                3.76                1.2
#3               180                5.84               3.06                3.76                1.2
#4               180                5.84               3.06                3.76                1.2
#5               180                5.84               3.06                3.76                1.2
#6               180                5.84               3.06                3.76                1.2

Comment puis-je sélectionner certaines colonnes que je souhaite muter, comme je l'avais fait avec select dans le premier cas?

Vous pouvez le faire en référençant les colonnes à muter (ou à laisser) en donnant leurs noms comme ici (mutate Sepal.Length, mais pas Species):

iris %>% mutate_each(funs(sum), Sepal.Length, -Species) %>% head()

De plus, vous pouvez utiliser des fonctions spéciales pour sélectionner les colonnes à muter, toutes les colonnes commençant par ou contenant un certain mot, etc., en utilisant par exemple:

iris %>% mutate_each(funs(sum), contains("Sepal"),  -Species) %>% head()

Pour plus d'informations sur ces fonctions, voir ?mutate_each Et ?select.

Éditer 1 après le commentaire:

Si vous souhaitez utiliser l'évaluation standard, dplyr fournit les versions SE de la plupart des fonctions se terminant par un "_" supplémentaire. Donc, dans ce cas, vous utiliseriez:

x <- c("Sepal.Width", "Sepal.Length") # vector of column names 
iris %>% mutate_each_(funs(sum), x) %>% head()

Notez le mutate_each_ Que j'ai utilisé ici.


Edit 2: mis à jour avec l'option a.4

103
docendo discimus

mutate_each Sera obsolète, envisagez d'utiliser mutate_at. De la documentation dplyr_0.5.0:

Dans le futur, mutate_each () et summary_each () seront déconseillés au profit d'une famille de fonctions plus complète: mutate_all (), mutate_at (), mutate_if (), summaryEdit (), summaryEdit () et summaryEdit () et summary_if ().

Appliquez une fonction à toutes les variables sauf Species:

Attention: le paramètre '.cols' est obsolète, voir note en bas!

iris %>% mutate_at(.cols=vars(-Species), .funs=funs(mysum = sum(.))) %>% head()

 Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length_mysum Sepal.Width_mysum
1          5.1         3.5          1.4         0.2  setosa              876.5             458.6
2          4.9         3.0          1.4         0.2  setosa              876.5             458.6
3          4.7         3.2          1.3         0.2  setosa              876.5             458.6
4          4.6         3.1          1.5         0.2  setosa              876.5             458.6
5          5.0         3.6          1.4         0.2  setosa              876.5             458.6
6          5.4         3.9          1.7         0.4  setosa              876.5             458.6
  Petal.Length_mysum Petal.Width_mysum
1              563.7             179.9
2              563.7             179.9
3              563.7             179.9
4              563.7             179.9
5              563.7             179.9
6              563.7             179.9

Appliquer une fonction à un sous-ensemble de variables

vars_to_process=c("Petal.Length","Petal.Width")
iris %>% mutate_at(.cols=vars_to_process, .funs=funs(mysum = sum(.))) %>% head()

 Sepal.Length Sepal.Width Petal.Length Petal.Width Species Petal.Length_mysum Petal.Width_mysum
1          5.1         3.5          1.4         0.2  setosa              563.7             179.9
2          4.9         3.0          1.4         0.2  setosa              563.7             179.9
3          4.7         3.2          1.3         0.2  setosa              563.7             179.9
4          4.6         3.1          1.5         0.2  setosa              563.7             179.9
5          5.0         3.6          1.4         0.2  setosa              563.7             179.9
6          5.4         3.9          1.7         0.4  setosa              563.7             179.9

Mise à jour! pour la version dplyr 0.7.1 (2017-08-08)

Si vous voyez le message:

.cols A été renommé et est déconseillé, veuillez utiliser .vars.

puis changez .cols par .vars.

iris %>% mutate_at(.vars=vars(-Species), .funs=funs(mysum = sum(.))) %>% head()

Un autre exemple:

iris %>% mutate_at(.vars=vars(Sepal.Width), .funs=funs(mysum = sum(.))) %>% head()

Est équivalent à:

iris %>% mutate_at(.vars=vars("Sepal.Width"), .funs=funs(mysum = sum(.))) %>% head()

De plus, dans cette version, le mutate_each Est obsolète:

mutate_each() est obsolète. Utilisez plutôt mutate_all(), mutate_at() ou mutate_if(). Pour mapper funs sur une sélection de variables, utilisez mutate_at()

13
pablo_sci