2013-08-16 6 views
14

ich zwei Variablen auf einem Grundstück ähnlich eine Bevölkerung darstellen möge Pyramide ähnlich, dies zu:Zwei horizontale Balkendiagramme mit gemeinsamer Achse in ggplot2 (ähnlich Bevölkerungspyramide)

plot

Dieses Grundstück ist fast da aber nicht ganz, aus den Gründen, die ich unten auflisten werde.

Ich produzierte dieses Grundstück mit dem folgenden Code:

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

ich zwei Parzellen back-to-back "kleben" will, so verwende ich die Multiplot() Funktion wörtlich aus http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_%28ggplot2%29/

(ich werde den Code für diese Funktion hier aus Gründen der Kürze und Klarheit)

Mein Code für die letzte Handlung ist nicht reproduzieren:

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. Also, was ist los mit dieser Handlung?

  • Ich muss die Teilstriche auf der rechten Achse des linken Diagramms erhalten. Ich kann nicht herausfinden, wie das geht.
  • Die beiden Grundstücke sind unterschiedlich breit. Dies liegt daran, dass die Zustände in der Mitte die Achsenbeschriftungen aus dem rechten Diagramm sind und einen Teil des Raums für dieses Diagramm verwenden.

Ich habe eine Ziegelmauer getroffen, um dieses Grundstück zu "Produktionsqualität" zu bekommen. Ich beginne mich zu fragen, ob ich das falsch mache, weil ich denke, der nächste Schritt wird darin bestehen, die Achsenbeschriftungen als separate dritte Spalte zwischen den beiden Plots zu zeichnen. (Ich weiß noch nicht, wie ich das machen soll). Dadurch wird das Problem der "gleichen Größe" gelöst und ich kann einen "Status" -Titel hinzufügen, so dass es immer noch der richtige Weg ist. Aber ich kann einfach nicht helfen, aber frage mich, ob es einen einfacheren Weg gibt ...

Alle Ratschläge oder Unterstützung geschätzt!

+1

Können Sie anpassen http://stackoverflow.com/questions/14680075/simpler-population-pyramid-in-ggplot2?lq=1 für Ihren Zweck? – mnel

+2

Ich bin ein eingefleischter 'ggplot2' Fan und benutze das Paket für absolut alles, was ich kann, aber als ich ein Pyramidenplot erstellen musste, das demjenigen vor ein paar Monaten ähnlich war, gab ich schließlich auf und benutzte' pyramid.plot' aus dem 'Plotterpaket'. Nein, ich mochte die Syntax nicht, aber es war nicht schwer und ich habe bessere Ergebnisse als mit 'ggplot2' und mit viel weniger Unordnung. – SlowLearner

+0

Sie sollten nach "Back-to-Back-Charts" suchen. –

Antwort

22

Hier ist eine sehr lange Problemumgehung für Ihre Handlung. Die Idee besteht darin, ein neues Diagramm zu erstellen, das nur Zustandsnamen und Häkchen auf beiden Seiten enthält und dieses dann als mittleres Diagramm verwendet.

Für dieses Diagramm habe ich Titel ohne Namen hinzugefügt, um Platz zu bekommen, und ylab(NULL), um Platz zu entfernen. Für den linken und rechten Rand sind die Werte -1, um das Diagramm näher an andere Diagramme zu bringen. Bibliothek grid sollte vor dem Plotten hinzugefügt werden, um die Funktion unit() für Plot-Ränder zu verwenden.

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

Beide Originalzeichnungen sind modifiziert. Zuerst wurde die y-Achse für die zweite Zeichnung entfernt und der linke/rechte Rand auf -1 gesetzt.

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

verwenden Jetzt Bibliothek gridExtra und Funktion d grid.arrange() Plots zu verbinden. Vor dem Plotten werden alle Plots als Grobs gemacht.

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 für große Anstrengungen! Und offensichtlich für die Beantwortung der OP –

+0

Etwas ähnliches wurde von Prasad vorgeschlagen http://stackoverflow.com/questions/4559229/drawing-pyramid-plot-using-r-and-ggplot2 –

+0

@ RomanLuštrik Es scheint so, aber ich habe es nicht das vorher gesehen :) –

Verwandte Themen