2013-03-05 13 views
8

Ich möchte etwas Hilfe beim Einfärben eines ggplot2-Histogramms, das aus bereits zusammengefassten Zähldaten generiert wurde.Gestapeltes Histogramm von bereits zusammengefassten Zählungen mit ggplot2

Die Daten sind so etwas wie Anzahl der # Männer und # Frauen in einer Reihe von verschiedenen Bereichen. Es ist leicht genug, um das Histogramm für die Gesamtzählungen plotten (dh Männer + Frauen):

set.seed(1) 
N=100; 
X=data.frame(C1=rnbinom(N,15,0.1), C2=rnbinom(N,15,0.1),C=rep(0,N)); 
X$C=X$C1+X$C2; 
ggplot(X,aes(x=C)) + geom_histogram() 

Allerdings würde Ich mag jede Bar Farbe entsprechend den relativen Beitrag von C1 und C2, so dass ich das bekommen das gleiche Histogramm (dh die Balkenhöhen insgesamt) wie im obigen Beispiel, plus ich sehe den Anteil der Typ "C1" und "C2" Personen wie in einem gestapelten Balkendiagramm.

Vorschläge für eine saubere Möglichkeit, dies mit ggplot2 zu tun, mit Daten wie "X" im Beispiel?

Antwort

9

Sehr schnell, können Sie tun, was der OP will die stat="identity" Option und das plyr Paket manuell das Histogramm zu berechnen, etwa so:

library(plyr) 

X$mid <- floor(X$C/20)*20+10 
X_plot <- ddply(X, .(mid), summarize, total=length(C), split=sum(C1)/sum(C)*length(C)) 

ggplot(data=X_plot) + geom_histogram(aes(x=mid, y=total), fill="blue", stat="identity") + geom_histogram(aes(x=mid, y=split), fill="deeppink", stat="identity") 

Wir haben im Grunde Machen Sie einfach eine "mids" -Spalte, um die Spalten zu lokalisieren, und erstellen Sie dann zwei Diagramme: eins mit der Zählung für die Summe (C) und eins mit den Spalten, angepasst an die Zählung einer der Spalten (C1). Sie sollten in der Lage sein, von hier aus anzupassen.

histogram demo

Update 1: Ich wurde mir klar, bei der Berechnung der mids einen kleinen Fehler gemacht. Jetzt behoben. Außerdem weiß ich nicht, warum ich eine 'ddply'-Anweisung verwendet habe, um die Mitten zu berechnen. Das war albern. Der neue Code ist klarer und prägnanter.

Update 2: Ich kehrte zu einem Kommentar zurück und bemerkte etwas leicht erschreckend: Ich benutzte Summen als Histogramm Frequenzen. Ich habe den Code ein wenig aufgeräumt und auch Vorschläge aus den Kommentaren zur Farbsyntax hinzugefügt.

+0

das ist gut, außer dass deine Legende verrückt ist. Beginnen Sie mit 'geom_histogram (aes (x = Mitte, y = total), fill =" blue ")' (d. H. Setzen Sie die 'fill'-Spezifikation außerhalb der Abbildung); Dann müssen Sie herausfinden, wie Sie die Anleitung (Legende) manuell hinzufügen können. –

+0

@BenBolker Ja, es ist nur eine schnelle Lösung, um die Daten korrekt anzuzeigen. Jetzt muss das OP nur noch von hier anpassen. – Dinre

0

Wie wäre:

library("reshape2") 
mm <- melt(X[,1:2]) 
ggplot(mm,aes(x=value,fill=variable))+geom_histogram(position="stack") 
+0

Ich glaube nicht, dass Werke, leider. Die Gesamtverteilung ist anders. Ich möchte z. B. 100 Individuen in der 100-Tonne behalten, aber die gesamte Aufschlüsselung von M und F in dieser Tonne färben. –

+0

@PaulJHurtado Ich glaube, Sie missverstehen Bens Code. Die Gesamtzählungen werden für jeden Behälter genau gleich sein, da sie gestapelt werden. Die 'melt'-Funktion verdichtet nur die Daten und dann setzt die Histogrammoption 'position =" stack "' die Variablen übereinander. Die Gesamthöhe wird gleich sein. Ich werde Bens Antwort ein paar Details hinzufügen, um es hoffentlich klarer zu machen. – Dinre

+0

Danke für die Mühe @Dinre. Achten Sie darauf, das Codebeispiel auszuführen, das ich gepostet und verglichen habe. Bens Beispiel gibt eine andere Gesamtverteilung. –

6

Hier ist ein Hack mit ggplot_build. Die Idee ist, zuerst die alte/ursprüngliche Grundstück zu erhalten:

p <- ggplot(data = X, aes(x=C)) + geom_histogram() 

in p gespeichert. Verwenden Sie dann ggplot_build(p)$data[[1]] die Daten zu extrahieren, insbesondere die Spalten xmin und xmax (um die gleichen Pausen/binwidths von Histogramm) und count Spalte (zur Normalisierung der Prozentsatz von count Hier ist der Code:.

# get old plot 
p <- ggplot(data = X, aes(x=C)) + geom_histogram() 
# get data of old plot: cols = count, xmin and xmax 
d <- ggplot_build(p)$data[[1]][c("count", "xmin", "xmax")] 
# add a id colum for ddply 
d$id <- seq(nrow(d)) 

Wie jetzt Daten zu generieren, was ich aus Ihrer Post verstehen ist Nehmen sie zum Beispiel der ersten Bar in Ihrem Grundstück es eine Zählung von 2 hat und es erstreckt sich von xmin = 147 zu xmax = 156.8 Wenn wir X für diese Werte überprüfen:?...

X[X$C >= 147 & X$C <= 156.8, ] # count = 2 as shown below 
# C1 C2 C 
# 19 91 63 154 
# 75 86 70 156 

Hier berechne ich (91+86)/(154+156)*(count=2) = 1.141935 und (63+70)/(154+156) * (count=2) = 0.8580645 als die beiden normalisierten Werte für jeden Balken, den wir generieren werden.

require(plyr) 
dd <- ddply(d, .(id), function(x) { 
    t <- X[X$C >= x$xmin & X$C <= x$xmax, ] 
    if(nrow(t) == 0) return(c(0,0)) 
    p <- colSums(t)[1:2]/colSums(t)[3] * x$count 
}) 

# then, it just normal plotting 
require(reshape2) 
dd <- melt(dd, id.var="id") 
ggplot(data = dd, aes(x=id, y=value)) + 
     geom_bar(aes(fill=variable), stat="identity", group=1) 

Und das ist das ursprüngliche Grundstück:

original_ggplot2_plot

Und das ist, was ich bekommen:

ggplot2_weird_histogram_plot

Edit: Wenn Sie auch das bekommen wollen Pausen richtig, dann können Sie die entsprechenden x Koordinaten erhalten und das alte Grundstück es verwendet hier statt id:

p <- ggplot(data = X, aes(x=C)) + geom_histogram() 
d <- ggplot_build(p)$data[[1]][c("count", "x", "xmin", "xmax")] 
d$id <- seq(nrow(d)) 

require(plyr) 
dd <- ddply(d, .(id), function(x) { 
    t <- X[X$C >= x$xmin & X$C <= x$xmax, ] 
    if(nrow(t) == 0) return(c(x$x,0,0)) 
    p <- c(x=x$x, colSums(t)[1:2]/colSums(t)[3] * x$count) 
}) 

require(reshape2) 
dd.m <- melt(dd, id.var="V1", measure.var=c("V2", "V3")) 
ggplot(data = dd.m, aes(x=V1, y=value)) + 
     geom_bar(aes(fill=variable), stat="identity", group=1) 

enter image description here

+0

Was ist Ihre Lösung, die '' require (reshape2); ggplot (schmelzen (X, id.vars = "C"), aes (x = C, fill = Variable)) + geom_histogram() 'nicht tun? – russellpierce

Verwandte Themen