Mostra% anziché conteggi nei grafici delle variabili categoriali


171

Sto disegnando una variabile categoriale e invece di mostrare i conteggi per ciascun valore di categoria.

Sto cercando un modo per ggplotvisualizzare la percentuale di valori in quella categoria. Certo, è possibile creare un'altra variabile con la percentuale calcolata e tracciarne una, ma devo farlo diverse dozzine di volte e spero di riuscirci in un solo comando.

Stavo sperimentando qualcosa del genere

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

ma devo usarlo in modo errato, poiché ho riscontrato errori.

Per riprodurre facilmente l'installazione, ecco un esempio semplificato:

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.

Nel caso reale, probabilmente userò ggplotinvece di qplot, ma il modo giusto di usare stat_bin mi sfugge ancora.

Ho anche provato questi quattro approcci:

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();

ma tutti e 4 danno:

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

Lo stesso errore appare per il semplice caso di

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

quindi è chiaramente qualcosa su come ggplotinteragisce con un singolo vettore. Mi gratto la testa, cercare su Google quell'errore dà un solo risultato .


2
I dati dovrebbero essere un frame di dati, non un fattore essenziale.
Hadley,

1
aggiungendo al commento di Hadley, convertendo i tuoi dati in un frame di dati usando mydataf = data.frame (mydataf) e rinominandolo come nomi (mydataf) = pippo farà il trucco
Ramnath,

Risposte:


222

Da quando è stata data una risposta, ci sono state alcune modifiche significative alla ggplotsintassi. Riassumendo la discussione nei commenti sopra:

 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)

Ecco un esempio riproducibile usando mtcars:

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

inserisci qui la descrizione dell'immagine

Questa domanda è attualmente il primo successo su google per "conteggio ggplot vs istogramma percentuale", quindi spero che questo aiuti a distillare tutte le informazioni attualmente ospitate nei commenti sulla risposta accettata.

Nota: se hpnon è impostato come fattore, ggplot restituisce:

inserisci qui la descrizione dell'immagine


12
Grazie per questa risposta Qualche idea su come farlo in classe?
WAF,

3
Come suggerisce @ WAF, questa risposta non funziona con i dati sfaccettati. Vedere @ commento di Erwan in stackoverflow.com/questions/22181132/...
LeeZamparo

1
Potrebbe essere necessario aggiungere un prefisso percental pacchetto da cui proviene per far funzionare quanto sopra (l'ho fatto). ggplot(mtcars, aes(x = factor(hp))) + geom_bar(aes(y = (..count..)/sum(..count..))) + scale_y_continuous(labels = scales::percent)
mammykins,

Per aggirare l'uso delle sfaccettature utilizzare geom_bar(aes(y = (..count..)/tapply(..count..,..PANEL..,sum)[..PANEL..]))invece. Ogni aspetto dovrebbe essere pari al 100%.
JWilliman,

Le variabili con ".." non sono state sostituite con il comando stat ()? ggplot2.tidyverse.org/reference/stat.html
Magnus

58

questo codice modificato dovrebbe funzionare

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

se i tuoi dati hanno NA e non vuoi che vengano inclusi nella trama, passa na.omit (mydataf) come argomento a ggplot.

spero che questo ti aiuti.


37
Nota che nella versione 0.9.0 di ggplot2 l' formatterargomento non funzionerà più. Invece, vorrai qualcosa di simile labels = percent_format()).
joran

25
E con 0.9.0 dovrai caricare la scaleslibreria prima dell'uso percent_format(), altrimenti non funzionerà. 0.9.0 non carica più automaticamente i pacchetti di supporto.
Andrew

1
Vedere ? stat_bin. Mostra quali colonne aggiuntive vengono aggiunte al frame di dati da ggplot2. Tutte le colonne extra sono nel modulo ..variable...
Ramnath,

1
Ha senso sostituirlo aes(y = (..count..)/sum(..count..))semplicemente aes(y = ..density..)? Visivamente dà un'immagine molto simile (ma ancora diversa)
Alexander Kosenkov,

6
In ggplot 0.9.3.1.0, dovrai prima caricare la scaleslibreria, quindi utilizzare scale_y_continuous(labels=percent)come indicato nei documenti
adilapapaya,

49

Con ggplot2 versione 2.1.0 lo è

+ scale_y_continuous(labels = scales::percent)

37

A partire da marzo 2017, con ggplot22.2.1 penso che la migliore soluzione sia spiegata nel libro di scienza dei dati di Hadley Wickham R:

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

stat_countcalcola due variabili: countviene utilizzato per impostazione predefinita, ma è possibile scegliere di utilizzare propche mostra le proporzioni.


3
Questa è la risposta migliore a giugno 2017, funziona con il riempimento per gruppo e con le sfaccettature.
Skumin,

1
Per qualche motivo ciò non mi consente di utilizzare la fillmappatura (non viene generato alcun errore, ma non viene aggiunto alcun colore di riempimento).
Max Candocia,

@MaxCandocia ho dovuto rimuovere group = 1per ottenere il mapping di riempimento. forse aiuta
Tjebo

1
Se rimuovo il groupparametro, tuttavia, non mostra le percentuali appropriate, poiché tutto appartiene al proprio gruppo per ciascun valore x univoco.
Max Candocia,

20

Se vuoi percentuali sull'asse y ed etichettate sulle barre:

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")

inserisci qui la descrizione dell'immagine

Quando aggiungi le etichette a barre, potresti voler omettere l'asse y per un grafico più pulito, aggiungendo alla fine:

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

inserisci qui la descrizione dell'immagine


6

Se vuoi etichette percentuali ma N effettivi sull'asse y, prova questo:

    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

Ecco una soluzione alternativa per i dati sfaccettati. (La risposta accettata da @Andrew non funziona in questo caso.) L'idea è di calcolare il valore percentuale usando dplyr e quindi usare geom_col per creare il grafico.

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~.)

Questa è la trama:

inserisci qui la descrizione dell'immagine


4

Nota che se la tua variabile è continua, dovrai usare geom_histogram (), poiché la funzione raggrupperà la variabile per "bin".

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..))) 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.