2016-06-14 16 views
5

Sto cercando un modo per etichettare un grafico a barre in pila con le percentuali mentre l'asse y mostra il conteggio originale (utilizzando ggplot). Ecco una MWE per la trama senza etichette:R: grafico a barre in pila ggplot con conteggi sull'asse y ma percentuale come etichetta

library(ggplot2) 
df <- as.data.frame(matrix(nrow = 7, ncol= 3, 
         data = c("ID1", "ID2", "ID3", "ID4", "ID5", "ID6", "ID7", 
           "north", "north", "north", "north", "south", "south", "south", 
           "A", "B", "B", "C", "A", "A", "C"), 
         byrow = FALSE)) 

colnames(df) <- c("ID", "region", "species") 

p <- ggplot(df, aes(x = region, fill = species)) 
p + geom_bar() 

Ho una tabella molto più grande e R conta molto bene le diverse specie per ogni regione. Ora, vorrei mostrare entrambi, il valore di conteggio originale (preferibilmente sull'asse y) e la percentuale (come etichetta) per confrontare le proporzioni di specie tra le regioni.

ho provato molte cose usando geom_text() ma credo che la differenza principale ad altre domande (e.g. this one) è che

  • non ho una colonna separata per valori di y (sono solo i conti di specie diverse per regione) e
  • Ho bisogno delle etichette per regione per riassumere fino al 100% (dal momento che sono considerate rappresentare popolazioni separate), non tutte le etichette dell'intero grafico.

Qualsiasi aiuto è molto apprezzato !!

+5

Quando stai facendo qualcosa di non standard, di solito devi calcolare i numeri da solo. Potrebbe * essere * possibile farlo all'interno di ggplot, ma non sarà semplice. Meglio usare le funzioni create per la manipolazione dei dati, quindi provare a manipolare i dati all'interno di ggplot. – Gregor

risposta

6

Come @Gregor menzionato, riepilogare i dati separatamente e quindi inviare il riepilogo dei dati a ggplot. Nel codice qui sotto, usiamo dplyr per creare la sintesi al volo:

library(dplyr) 

ggplot(df %>% count(region, species) %>% # Group by region and species, then count number in each group 
     mutate(pct=n/sum(n),    # Calculate percent within each region 
       ypos = cumsum(n) - 0.5*n), # Calculate label positions 
     aes(region, n, fill=species)) + 
    geom_bar(stat="identity") + 
    geom_text(aes(label=paste0(sprintf("%1.1f", pct*100),"%"), y=ypos)) 

enter image description here

Aggiornamento: Con dplyr 0,5 e più tardi, non è più necessario per fornire un valore y al centro il testo all'interno di ogni barra. Invece è possibile utilizzare position_stack(vjust=0.5):

ggplot(df %>% count(region, species) %>% # Group by region and species, then count number in each group 
     mutate(pct=n/sum(n)),    # Calculate percent within each region 
     aes(region, n, fill=species)) + 
    geom_bar(stat="identity") + 
    geom_text(aes(label=paste0(sprintf("%1.1f", pct*100),"%")), 
      position=position_stack(vjust=0.5)) 
+1

Grazie mille, questo è esattamente quello che stavo cercando! – Johanna

+0

Si noti che il codice presentato sopra NON produrrà il barplot mostrato! Devi usare un comando 'group_by' in aggiunta a quello:' df%>% group_by (region)%>% count (region, species)%>% mutate (pct = n/sum (n) ' –

+0

' group_by' non è necessario. 'count (x, y)' è l'equivalente di 'group_by (x, y)%>% tally'. – eipi10

1

Sono d'accordo con Johanna. Potresti provare:

d <- aggregate(.~region+species, df, length) 
d$percent <- paste(round(ID/sum(ID)*100),'%',sep='') 
ggplot(d, aes(region, ID, fill=species)) + geom_bar(stat='identity') + 
    geom_text(position='stack', aes(label=paste(round(ID/sum(ID)*100),'%',sep='')), vjust=5) 
+0

Grazie per l'input, ma nella soluzione le percentuali per stack non si sommano al 100%. BTW: Suppongo che dovrebbe essere 'd $ percent <- incolla (round (d $ ID/somma (d $ ID) * 100), '%', sep = '')'. – Johanna