3 votes

"summarise_at" et "mutate_if" pour les statistiques descriptives des variables de caractère

Je voudrais utiliser summarise_at y mutate_at sur plusieurs variables de caractères en même temps. J'ai examiné de nombreux exemples qui utilisent des variables entières, mais je n'arrive pas à comprendre ce qui se passe avec les variables de type caractère. Ci-dessous se trouve le code que j'utilise pour produire des statistiques descriptives pour une variable de caractère (ou facteur).

library(tidyverse)

# First block of code
starwars %>%
  group_by(gender) %>%
  summarise (n = n()) %>%
  mutate(totalN = (cumsum(n))) %>%
  mutate(percent = round((n / sum(n)), 3)) %>%
  mutate(cumpercent = round(cumsum(freq = n / sum(n)),3))

Cela produit :

A tibble: 5 x 5
         gender     n totalN percent cumpercent
          <chr> <int>  <int>   <dbl>      <dbl>
1        female    19     19   0.218      0.218
2 hermaphrodite     1     20   0.011      0.230
3          male    62     82   0.713      0.943
4          none     2     84   0.023      0.966
5          <NA>     3     87   0.034      1.000

Je voudrais produire la même chose, mais pour plusieurs variables de caractères (ou de facteurs) à la fois. Dans ce cas, utilisons les variables gender y eye_color C'est ce que j'ai essayé :

starwars %>%        
      summarise_at(vars(gender, eyecolor) (n = n()) %>%
      mutate_at(vars(gender, eyecolor) (totalN = (cumsum(n))) %>%
      mutate_at(vars(gender", "eyecolor) (percent = round((n / sum(n)), 3)) %>%
      mutate_at(vars(gender, eyecolor) (cumpercent = round(cumsum(freq = n / sum(n)),3))))))

Je reçois l'erreur suivante :

Error in eval(expr, envir, enclos) : attempt to apply non-function

Je comprends qu'il existe des fonctions intégrées appelées funs mais je ne veux pas les utiliser. J'ai essayé de jouer avec le code de plusieurs façons différentes pour qu'il fonctionne, mais je n'ai rien trouvé.

Ce que je voudrais produire, c'est quelque chose comme ça :

A tibble: 5 x 5
         gender     n totalN percent cumpercent
          <chr> <int>  <int>   <dbl>      <dbl>
1        female    19     19   0.218      0.218
2 hermaphrodite     1     20   0.011      0.230
3          male    62     82   0.713      0.943
4          none     2     84   0.023      0.966
5          <NA>     3     87   0.034      1.000

A tibble: 15 x 5
      eye_color     n totalN percent cumpercent
          <chr> <int>  <int>   <dbl>      <dbl>
1         black    10     10   0.115      0.115
2          blue    19     29   0.218      0.333
3     blue-gray     1     30   0.011      0.345
4         brown    21     51   0.241      0.586
5          dark     1     52   0.011      0.598
6          gold     1     53   0.011      0.609
7 green, yellow     1     54   0.011      0.621
8         hazel     3     57   0.034      0.655
9        orange     8     65   0.092      0.747
10         pink     1     66   0.011      0.759
11          red     5     71   0.057      0.816
12     red, blue    1     72   0.011      0.828
13       unknown    3     75   0.034      0.862
14         white    1     76   0.011      0.874
15        yellow    11     87   0.126     1.000

Peut-être qu'une boucle serait préférable ? Actuellement, j'ai de nombreuses lignes de code pour générer les statistiques descriptives de chaque variable de caractère, car je dois exécuter le premier bloc de code (indiqué ci-dessus) pour chaque variable. Ce serait formidable si je pouvais simplement dresser la liste des variables que je souhaite utiliser et les exécuter dans le premier bloc de code.

3voto

avid_useR Points 11344

En fonction de vos résultats attendus, mutate_at n'est pas ce que vous voulez, puisqu'il mute sur les colonnes sélectionnées. Ce que vous vouliez faire, c'est group_by gender y eye_color séparément. C'est un bon endroit pour écrire votre code de résumé dans une fonction :

library(tidyverse)
library(rlang)

summary_func = function(group_by_var){
  group_by_quo = enquo(group_by_var)
  starwars %>%
    group_by(!!group_by_quo) %>%
    summarise(n = n()) %>%
    mutate(totalN = (cumsum(n)),
           percent = round((n / sum(n)), 3),
           cumpercent = round(cumsum(freq = n / sum(n)),3))
}

Résultat :

> summary_func(gender)
# A tibble: 5 x 5
         gender     n totalN percent cumpercent
          <chr> <int>  <int>   <dbl>      <dbl>
1        female    19     19   0.218      0.218
2 hermaphrodite     1     20   0.011      0.230
3          male    62     82   0.713      0.943
4          none     2     84   0.023      0.966
5          <NA>     3     87   0.034      1.000

> summary_func(eye_color)
# A tibble: 15 x 5
       eye_color     n totalN percent cumpercent
           <chr> <int>  <int>   <dbl>      <dbl>
 1         black    10     10   0.115      0.115
 2          blue    19     29   0.218      0.333
 3     blue-gray     1     30   0.011      0.345
 4         brown    21     51   0.241      0.586
 5          dark     1     52   0.011      0.598
 6          gold     1     53   0.011      0.609
 7 green, yellow     1     54   0.011      0.621
 8         hazel     3     57   0.034      0.655
 9        orange     8     65   0.092      0.747
10          pink     1     66   0.011      0.759
11           red     5     71   0.057      0.816
12     red, blue     1     72   0.011      0.828
13       unknown     3     75   0.034      0.862
14         white     1     76   0.011      0.874
15        yellow    11     87   0.126      1.000

L'idée est de transformer votre code de résumé en une fonction afin de pouvoir appliquer le même code à différents types d'applications. group_by variables. enquo de rlang prend le code fourni à group_by_var et le regroupe avec l'environnement dans lequel il a été appelé dans un fichier quosure . Vous pouvez alors utiliser !! de ne pas citer le group_by_quo dans le group_by étape. Cela permet de procéder à une évaluation non standard (c'est-à-dire de taper summary_func(gender) au lieu de summary_func("gender") .

Si vous ne voulez pas appeler summary_func pour chaque variable que vous voulez group_by vous pouvez envelopper votre dplyr code dans map de purrr et dé-citer chaque argument de group_by_quo fourni en tant que ... arguments. Remarquez le changement de enquo a quos pour convertir chaque argument de ... à une liste de quosure s :

summary_func = function(...){
  group_by_quo = quos(...)

  map(group_by_quo, ~{
    starwars %>%
      group_by(!!.x) %>%
      summarise(n = n()) %>%
      mutate(totalN = (cumsum(n)),
             percent = round((n / sum(n)), 3),
             cumpercent = round(cumsum(freq = n / sum(n)),3))
  })
}

Vous pouvez maintenant le faire :

summary_func(gender, eye_color)

ou avec un vecteur de noms de variables de caractères pour group_by :

group_vars = c("gender", "eye_color")
summary_func(!!!syms(group_vars))

Résultat :

[[1]]
# A tibble: 5 x 5
         gender     n totalN percent cumpercent
          <chr> <int>  <int>   <dbl>      <dbl>
1        female    19     19   0.218      0.218
2 hermaphrodite     1     20   0.011      0.230
3          male    62     82   0.713      0.943
4          none     2     84   0.023      0.966
5          <NA>     3     87   0.034      1.000

[[2]]
# A tibble: 15 x 5
       eye_color     n totalN percent cumpercent
           <chr> <int>  <int>   <dbl>      <dbl>
 1         black    10     10   0.115      0.115
 2          blue    19     29   0.218      0.333
 3     blue-gray     1     30   0.011      0.345
 4         brown    21     51   0.241      0.586
 5          dark     1     52   0.011      0.598
 6          gold     1     53   0.011      0.609
 7 green, yellow     1     54   0.011      0.621
 8         hazel     3     57   0.034      0.655
 9        orange     8     65   0.092      0.747
10          pink     1     66   0.011      0.759
11           red     5     71   0.057      0.816
12     red, blue     1     72   0.011      0.828
13       unknown     3     75   0.034      0.862
14         white     1     76   0.011      0.874
15        yellow    11     87   0.126      1.000

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X