Fréquences / proportions relatives avec dplyr

Supposons que je veuille calculer la proportion de valeurs différentes dans chaque groupe. Par exemple, en utilisant les données mtcars, Comment calculer la relative fréquence du nombre de engrenages par am (Automatique/Manuel) en une seule fois avec dplyr?

library(dplyr)
data(mtcars)
mtcars <- tbl_df(mtcars)

# count frequency
mtcars %>%
  group_by(am, gear) %>%
  summarise(n = n())

# am gear  n
#  0    3 15 
#  0    4  4 
#  1    4  8  
#  1    5  5 

Ce que je voudrais réaliser:

am gear  n rel.freq
 0    3 15      0.7894737
 0    4  4      0.2105263
 1    4  8      0.6153846
 1    5  5      0.3846154
93
demandé sur jenswirf 2014-07-04 18:31:15

5 réponses

, Essayez ceci:

mtcars %>%
  group_by(am, gear) %>%
  summarise (n = n()) %>%
  mutate(freq = n / sum(n))

#   am gear  n      freq
# 1  0    3 15 0.7894737
# 2  0    4  4 0.2105263
# 3  1    4  8 0.6153846
# 4  1    5  5 0.3846154

De la vignette dplyr:

Lorsque vous groupez par plusieurs variables, chaque résumé se détache d'un niveau du regroupement. Cela facilite l'enroulement progressif d'un ensemble de données.

Ainsi, après le summarise, la variable de regroupement 'gear' est décollée, et les données sont ensuite regroupées 'only' par 'am' (il suffit de le vérifier avec groups sur les données résultantes), sur lequel nous effectuons ensuite le calcul mutate.

Le résultat de le 'peeling' dépend bien sûr de l'ordre des variables de regroupement dans l'appel group_by. Nous avons eu de la chance cette fois, qu'il décollé de la variable souhaitée. Vous voudrez peut-être faire un group_by(am) suivant, pour rendre votre code plus explicite.

Pour l'arrondi et la prettification, veuillez vous référer à la belle réponse de @ Tyler Rinker.

182
répondu Henrik 2018-01-28 17:35:42

Vous pouvez utiliser la fonction count(), qui a cependant un comportement différent en fonction de la version de dplyr:

  • Dplyr 0.7.1: renvoie une table ungrouped : Vous devez grouper à nouveau par am

  • Dplyr groupée , donc pas besoin de grouper à nouveau, bien que vous souhaitiez peut-être ungroup() pour les manipulations ultérieures

Dplyr 0.7.1

mtcars %>%
  count(am, gear) %>%
  group_by(am) %>%
  mutate(freq = n / sum(n))

Dplyr

mtcars %>%
  count(am, gear) %>%
  mutate(freq = n / sum(n))

Ce résultat dans un regroupés table, si vous voulez l'utiliser pour une analyse plus approfondie, il peut être utile de retirer le regroupés attribut avec ungroup().

25
répondu Matifou 2017-07-19 21:49:42

@Henrik's est meilleur pour la facilité d'utilisation car cela rendra le caractère de la colonne et non plus numérique mais correspond à ce que vous avez demandé...

mtcars %>%
  group_by (am, gear) %>%
  summarise (n=n()) %>%
  mutate(rel.freq = paste0(round(100 * n/sum(n), 0), "%"))

##   am gear  n rel.freq
## 1  0    3 15      79%
## 2  0    4  4      21%
## 3  1    4  8      62%
## 4  1    5  5      38%

EDIT parce que Spacedman l'a demandé: -)

as.rel_freq <- function(x, rel_freq_col = "rel.freq", ...) {
    class(x) <- c("rel_freq", class(x))
    attributes(x)[["rel_freq_col"]] <- rel_freq_col
    x
}

print.rel_freq <- function(x, ...) {
    freq_col <- attributes(x)[["rel_freq_col"]]
    x[[freq_col]] <- paste0(round(100 * x[[freq_col]], 0), "%")   
    class(x) <- class(x)[!class(x)%in% "rel_freq"]
    print(x)
}

mtcars %>%
  group_by (am, gear) %>%
  summarise (n=n()) %>%
  mutate(rel.freq = n/sum(n)) %>%
  as.rel_freq()

## Source: local data frame [4 x 4]
## Groups: am
## 
##   am gear  n rel.freq
## 1  0    3 15      79%
## 2  0    4  4      21%
## 3  1    4  8      62%
## 4  1    5  5      38%
20
répondu Tyler Rinker 2014-07-04 18:35:57

Voici une fonction générale implémentant la solution de Henrik sur dplyr 0.7.1.

freq_table <- function(x, 
                       group_var, 
                       prop_var) {
  group_var <- enquo(group_var)
  prop_var  <- enquo(prop_var)
  x %>% 
    group_by(!!group_var, !!prop_var) %>% 
    summarise(n = n()) %>% 
    mutate(freq = n /sum(n)) %>% 
    ungroup
}
3
répondu Edwin 2017-07-19 14:18:36

Cette réponse est basée sur la réponse de Matifou.

D'abord, je l'ai modifié pour m'assurer que je n'obtiens pas la colonne freq retournée en tant que Colonne de notation scientifique en utilisant l'option scipen.

Ensuite, je multiple la réponse par 100 pour obtenir un pourcentage plutôt que décimal pour rendre la colonne freq plus facile à lire en pourcentage.

getOption("scipen") 
options("scipen"=10) 
mtcars %>%
count(am, gear) %>% 
mutate(freq = (n / sum(n)) * 100)
1
répondu Jazzmine 2016-12-22 11:28:43