2013-08-16 20 views
14

Voglio tracciare due variabili su una trama simile a una popolazione piramide simile a questo:Due grafici a barre orizzontali con asse condiviso in ggplot2 (simili a piramide della popolazione)

plot

Questa trama è quasi lì, ma non del tutto, per i motivi che elencherò di seguito.

ho prodotto questa trama con il seguente codice:

DATA <- data.frame(
    state = c("AK", "TX", "CA", "MT", "NM", "AZ", "NV", "CO", "OR", "WY", "MI", "MN", "UT", "ID", "KS", "NE", "SD", "WA", "ND", "OK"), 
    sales_staff = c(20,30,40,10,15,35,18,25,22,7,12,22,3,4,5,8,14,28,24,32) 
) 

set.seed(1) 
DATA$sales <- DATA$sales_staff * 50 + (runif(nrow(DATA)) * 1000) 

# Order the state factor by number of sales staff so that it is plotted in that order 
DATA$state <- factor(DATA$state, levels = DATA[order(DATA$sales_staff),"state"]) 

voglio "colla" due lotti back-to-back, per cui uso il multiplo() funzione testualmente http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_%28ggplot2%29/

(non voglio riprodurre il codice per quella funzione qui per brevità e chiarezza)

il mio codice per la trama finale è:

library(ggplot2) 

g1 <- ggplot(data = DATA, aes(x = state, y = sales_staff)) + 
    geom_bar(stat = "identity") + ggtitle("Number of sales staff") + 
    theme(axis.title.x = element_blank(), axis.title.y = element_blank(), axis.text.y = element_blank(), axis.ticks.y = element_blank(), plot.margin = unit(c(1,0,1,0), "mm")) + 
    scale_y_reverse() + coord_flip() 

g2 <- ggplot(data = DATA, aes(x = state, y = sales)) + 
    geom_bar(stat = "identity") + ggtitle("Sales (x $1000)") + 
    theme(axis.title.x = element_blank(), axis.title.y = element_blank(), plot.margin = unit(c(1,5,1,0), "mm")) + 
    coord_flip() 

multiplot(g1, g2, cols = 2) 

OK. Allora, cosa c'è di sbagliato in questa trama?

  • Ho bisogno di ottenere i segni di graduazione sull'asse destro del grafico di sinistra. Non riesco a capire come farlo.
  • I due grafici hanno diverse larghezze. Questo perché gli stati nel mezzo sono le etichette degli assi dalla trama giusta e usano un po 'dello spazio per quella trama.

Ho colpito un muro di mattoni per ottenere questa trama di "qualità di produzione". Sto iniziando a chiedermi se sto andando in questo modo nel modo sbagliato, perché sto pensando che il prossimo passo sarà quello di disegnare le etichette degli assi come terza colonna separata tra i due grafici. (Non so ancora come farlo). Questo risolverà il problema della "dimensione uguale" e mi consentirà di aggiungere un titolo di "stato", quindi potrebbe essere ancora la strada da percorrere. Ma non posso fare a meno di chiedermi se c'è un modo più semplice ...

Qualsiasi consiglio o assistenza apprezzati!

+1

Potete regolare http://stackoverflow.com/questions/14680075/simpler-population-pyramid-in-ggplot2?lq=1 per il vostro scopo? – mnel

+2

Sono un appassionato fan di 'ggplot2' e uso il pacchetto per assolutamente tutto ciò che posso, ma quando ho avuto bisogno di creare una trama piramidale simile a quella sopra qualche mese fa alla fine ho rinunciato e ho usato' pyramid.plot' dal pacchetto 'plotrix'. No, non mi piaceva la sintassi, ma non era difficile e ho ottenuto risultati migliori rispetto a 'ggplot2' e con molto meno confusione. – SlowLearner

+0

È necessario cercare "diagrammi back to back". –

risposta

22

Ecco una soluzione molto lunga per la trama. L'idea è di creare una nuova trama che contenga solo nomi di stati e segni di spunta su entrambi i lati e quindi utilizzarla come trama centrale.

Per questa trama ho aggiunto il titolo senza nome per ottenere spazio e ylab(NULL) per rimuovere lo spazio. Per i valori di margine sinistro e destro sono -1 per avvicinare la trama ad altri grafici. La libreria grid deve essere aggiunta prima di stampare per utilizzare la funzione unit() per i margini di stampa.

library(grid) 
g.mid<-ggplot(DATA,aes(x=1,y=state))+geom_text(aes(label=state))+ 
    geom_segment(aes(x=0.94,xend=0.96,yend=state))+ 
    geom_segment(aes(x=1.04,xend=1.065,yend=state))+ 
    ggtitle("")+ 
    ylab(NULL)+ 
    scale_x_continuous(expand=c(0,0),limits=c(0.94,1.065))+ 
    theme(axis.title=element_blank(), 
     panel.grid=element_blank(), 
     axis.text.y=element_blank(), 
     axis.ticks.y=element_blank(), 
     panel.background=element_blank(), 
     axis.text.x=element_text(color=NA), 
     axis.ticks.x=element_line(color=NA), 
     plot.margin = unit(c(1,-1,1,-1), "mm")) 

Entrambi i grafici originali vengono modificati. In primo luogo, rimosso l'asse y per il secondo grafico e reso anche il margine sinistro/destro a -1.

g1 <- ggplot(data = DATA, aes(x = state, y = sales_staff)) + 
    geom_bar(stat = "identity") + ggtitle("Number of sales staff") + 
    theme(axis.title.x = element_blank(), 
     axis.title.y = element_blank(), 
     axis.text.y = element_blank(), 
     axis.ticks.y = element_blank(), 
     plot.margin = unit(c(1,-1,1,0), "mm")) + 
    scale_y_reverse() + coord_flip() 

g2 <- ggplot(data = DATA, aes(x = state, y = sales)) +xlab(NULL)+ 
    geom_bar(stat = "identity") + ggtitle("Sales (x $1000)") + 
    theme(axis.title.x = element_blank(), axis.title.y = element_blank(), 
     axis.text.y = element_blank(), axis.ticks.y = element_blank(), 
     plot.margin = unit(c(1,0,1,-1), "mm")) + 
    coord_flip() 

Ora usare biblioteca gridExtra e la funzione d grid.arrange() di unirsi trame. Prima di tracciare tutti i grafici sono fatti come trecce.

library(gridExtra) 
gg1 <- ggplot_gtable(ggplot_build(g1)) 
gg2 <- ggplot_gtable(ggplot_build(g2)) 
gg.mid <- ggplot_gtable(ggplot_build(g.mid)) 

grid.arrange(gg1,gg.mid,gg2,ncol=3,widths=c(4/9,1/9,4/9)) 

enter image description here

+2

+1 per copiosi sforzi! E ovviamente per rispondere all'OP –

+0

Qualcosa di simile è stato suggerito da Prasad http://stackoverflow.com/questions/4559229/drawing-pyramid-plot-using-r-and-ggplot2 –

+0

@ RomanLuštrik Sembra così ma non l'ho fatto visto prima :) –

Problemi correlati