Afficher le% au lieu des nombres dans les graphiques de variables catégorielles


171

Je trace une variable catégorielle et au lieu d'afficher les nombres pour chaque valeur de catégorie.

Je cherche un moyen d' ggplotafficher le pourcentage de valeurs dans cette catégorie. Bien sûr, il est possible de créer une autre variable avec le pourcentage calculé et de tracer celle-là, mais je dois le faire plusieurs dizaines de fois et j'espère y parvenir en une seule commande.

J'expérimentais quelque chose comme

qplot(mydataf) +
  stat_bin(aes(n = nrow(mydataf), y = ..count../n)) +
  scale_y_continuous(formatter = "percent")

mais je dois l'utiliser de manière incorrecte, car j'ai des erreurs.

Pour reproduire facilement la configuration, voici un exemple simplifié:

mydata <- c ("aa", "bb", NULL, "bb", "cc", "aa", "aa", "aa", "ee", NULL, "cc");
mydataf <- factor(mydata);
qplot (mydataf); #this shows the count, I'm looking to see % displayed.

Dans le cas réel, j'utiliserai probablement à la ggplotplace de qplot, mais la bonne façon d'utiliser stat_bin m'échappe toujours.

J'ai également essayé ces quatre approches:

ggplot(mydataf, aes(y = (..count..)/sum(..count..))) + 
  scale_y_continuous(formatter = 'percent');

ggplot(mydataf, aes(y = (..count..)/sum(..count..))) + 
  scale_y_continuous(formatter = 'percent') + geom_bar();

ggplot(mydataf, aes(x = levels(mydataf), y = (..count..)/sum(..count..))) + 
  scale_y_continuous(formatter = 'percent');

ggplot(mydataf, aes(x = levels(mydataf), y = (..count..)/sum(..count..))) + 
  scale_y_continuous(formatter = 'percent') + geom_bar();

mais tous les 4 donnent:

Error: ggplot2 doesn't know how to deal with data of class factor

La même erreur apparaît pour le cas simple de

ggplot (data=mydataf, aes(levels(mydataf))) +
  geom_bar()

il s'agit donc clairement de la façon dont ggplotinteragit avec un seul vecteur. Je me gratte la tête, googler cette erreur donne un seul résultat .


2
Les données doivent être une trame de données et non un simple facteur.
hadley

1
ajouter au commentaire de hadley, convertir vos données en une trame de données en utilisant mydataf = data.frame (mydataf), et le renommer en tant que noms (mydataf) = foo fera l'affaire
Ramnath

Réponses:


222

Depuis que cela a été répondu, certains changements significatifs ont été apportés à la ggplotsyntaxe. Résumant la discussion dans les commentaires ci-dessus:

 require(ggplot2)
 require(scales)

 p <- ggplot(mydataf, aes(x = foo)) +  
        geom_bar(aes(y = (..count..)/sum(..count..))) + 
        ## version 3.0.0
        scale_y_continuous(labels=percent)

Voici un exemple reproductible utilisant mtcars:

 ggplot(mtcars, aes(x = factor(hp))) +  
        geom_bar(aes(y = (..count..)/sum(..count..))) + 
        scale_y_continuous(labels = percent) ## version 3.0.0

entrez la description de l'image ici

Cette question est actuellement le hit n ° 1 sur Google pour `` le nombre de ggplot vs l'histogramme en pourcentage '', donc j'espère que cela aidera à distiller toutes les informations actuellement contenues dans les commentaires sur la réponse acceptée.

Remarque: si hpn'est pas défini comme facteur, ggplot renvoie:

entrez la description de l'image ici


12
Merci pour cette réponse. Une idée sur la façon de le faire en classe?
WAF

3
Comme le suggère. @ WAF, cette réponse ne fonctionne pas avec des données à facettes. Voir le commentaire de @ Erwan dans stackoverflow.com/questions/22181132/…
LeeZamparo

1
Vous devrez peut-être ajouter percentun préfixe au package d'origine pour que ce qui précède fonctionne (c'est ce que j'ai fait). ggplot(mtcars, aes(x = factor(hp))) + geom_bar(aes(y = (..count..)/sum(..count..))) + scale_y_continuous(labels = scales::percent)
mammykins

Pour contourner l'utilisation des facettes, utilisez geom_bar(aes(y = (..count..)/tapply(..count..,..PANEL..,sum)[..PANEL..]))plutôt. Chaque facette doit totaliser 100%.
JWilliman

Les variables entourées de ".." n'ont-elles pas été remplacées par la commande stat ()? ggplot2.tidyverse.org/reference/stat.html
Magnus

58

ce code modifié devrait fonctionner

p = ggplot(mydataf, aes(x = foo)) + 
    geom_bar(aes(y = (..count..)/sum(..count..))) + 
    scale_y_continuous(formatter = 'percent')

si vos données ont des NA et que vous ne voulez pas qu'elles soient incluses dans le tracé, passez na.omit (mydataf) comme argument à ggplot.

J'espère que cela t'aides.


37
Notez que dans ggplot2 version 0.9.0, l' formatterargument ne fonctionnera plus. Au lieu de cela, vous voudrez quelque chose comme labels = percent_format()).
joran

25
Et avec la version 0.9.0, vous devrez charger la scalesbibliothèque avant de l'utiliser percent_format(), sinon cela ne fonctionnera pas. La 0.9.0 ne charge plus automatiquement les packages de support.
Andrew

1
Voir ? stat_bin. Il montre par quelles colonnes supplémentaires sont ajoutées le bloc de données ggplot2. Toutes les colonnes supplémentaires sont de la forme ..variable...
Ramnath

1
Est-il logique de remplacer aes(y = (..count..)/sum(..count..))par simplement aes(y = ..density..)? Visuellement, cela donne une image très similaire (mais toujours différente)
Alexander Kosenkov

6
Dans ggplot 0.9.3.1.0, vous voudrez d'abord charger la scalesbibliothèque, puis l'utiliser scale_y_continuous(labels=percent)comme mentionné dans la documentation
adilapapaya

49

Avec ggplot2 version 2.1.0 c'est

+ scale_y_continuous(labels = scales::percent)

37

En mars 2017, avec ggplot22.2.1, je pense que la meilleure solution est expliquée dans le livre de Hadley Wickham sur la science des données:

ggplot(mydataf) + stat_count(mapping = aes(x=foo, y=..prop.., group=1))

stat_countcalcule deux variables: countest utilisé par défaut, mais vous pouvez choisir d'utiliser propce qui montre les proportions.


3
C'est la meilleure réponse à partir de juin 2017, fonctionne avec remplissage par groupe et avec facettage.
Skumin

1
Pour une raison quelconque, cela ne me permet pas d'utiliser le fillmappage (aucune erreur n'est générée, mais aucune couleur de remplissage n'est ajoutée).
Max Candocia

@MaxCandocia j'ai dû supprimer group = 1pour obtenir le mappage de remplissage. peut-être que ça aide
Tjebo

1
Si je supprime le groupparamètre, cependant, il n'affiche pas les pourcentages appropriés, car tout appartient à son propre groupe pour chaque valeur x unique.
Max Candocia

20

Si vous voulez des pourcentages sur l'axe des y et étiquetés sur les barres:

library(ggplot2)
library(scales)
ggplot(mtcars, aes(x = as.factor(am))) +
  geom_bar(aes(y = (..count..)/sum(..count..))) +
  geom_text(aes(y = ((..count..)/sum(..count..)), label = scales::percent((..count..)/sum(..count..))), stat = "count", vjust = -0.25) +
  scale_y_continuous(labels = percent) +
  labs(title = "Manual vs. Automatic Frequency", y = "Percent", x = "Automatic Transmission")

entrez la description de l'image ici

Lors de l'ajout des étiquettes de barre, vous souhaiterez peut-être omettre l'axe des y pour un graphique plus propre, en ajoutant à la fin:

  theme(
        axis.text.y=element_blank(), axis.ticks=element_blank(),
        axis.title.y=element_blank()
  )

entrez la description de l'image ici


6

Si vous voulez des étiquettes de pourcentage mais des N réels sur l'axe des y, essayez ceci:

    library(scales)
perbar=function(xx){
      q=ggplot(data=data.frame(xx),aes(x=xx))+
      geom_bar(aes(y = (..count..)),fill="orange")
       q=q+    geom_text(aes(y = (..count..),label = scales::percent((..count..)/sum(..count..))), stat="bin",colour="darkgreen") 
      q
    }
    perbar(mtcars$disp)

6

Voici une solution de contournement pour les données à facettes. (La réponse acceptée par @Andrew ne fonctionne pas dans ce cas.) L'idée est de calculer la valeur en pourcentage en utilisant dplyr, puis d'utiliser geom_col pour créer le tracé.

library(ggplot2)
library(scales)
library(magrittr)
library(dplyr)

binwidth <- 30

mtcars.stats <- mtcars %>%
  group_by(cyl) %>%
  mutate(bin = cut(hp, breaks=seq(0,400, binwidth), 
               labels= seq(0+binwidth,400, binwidth)-(binwidth/2)),
         n = n()) %>%
  group_by(cyl, bin) %>%
  summarise(p = n()/n[1]) %>%
  ungroup() %>%
  mutate(bin = as.numeric(as.character(bin)))

ggplot(mtcars.stats, aes(x = bin, y= p)) +  
  geom_col() + 
  scale_y_continuous(labels = percent) +
  facet_grid(cyl~.)

Voici l'intrigue:

entrez la description de l'image ici


4

Notez que si votre variable est continue, vous devrez utiliser geom_histogram (), car la fonction regroupera la variable par "bins".

df <- data.frame(V1 = rnorm(100))

ggplot(df, aes(x = V1)) +  
  geom_histogram(aes(y = (..count..)/sum(..count..))) 

# if you use geom_bar(), with factor(V1), each value of V1 will be treated as a
# different category. In this case this does not make sense, as the variable is 
# really continuous. With the hp variable of the mtcars (see previous answer), it 
# worked well since hp was not really continuous (check unique(mtcars$hp)), and one 
# can want to see each value of this variable, and not to group it in bins.
ggplot(df, aes(x = factor(V1))) +  
  geom_bar(aes(y = (..count..)/sum(..count..))) 
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.