2009-11-14 9 views
18

Ich habe mit dem Erstellen eines Pareto Chart in R mit dem Ggplot2-Paket gekämpft. In vielen Fällen möchten wir beim Erstellen eines Balkendiagramms oder Histogramms Objekte nach der X-Achse sortieren. In einem Pareto-Diagramm möchten wir, dass die Objekte absteigend nach dem Wert in der Y-Achse sortiert werden. Gibt es eine Möglichkeit, mit ggplot Elemente nach dem Wert in der Y-Achse zu sortieren? Ich habe versucht, zuerst den Datenrahmen zu sortieren, aber es scheint, dass ggplot sie neu sortiert.Erstellen eines Pareto-Diagramms mit ggplot2 und R

Beispiel:

val <- read.csv("http://www.cerebralmastication.com/wp-content/uploads/2009/11/val.txt") 
val<-with(val, val[order(-Value), ]) 
p <- ggplot(val) 
p + geom_bar(aes(State, Value, fill=variable), stat = "identity", position="dodge") + scale_fill_brewer(palette = "Set1") 

der Datenrahmen val sortiert ist aber die Ausgabe wie folgt aussieht:

alt text http://www.cerebralmastication.com/wp-content/uploads/2009/11/exp.png

Hadley wies darauf hin, richtig, dass dies eine viel bessere Grafik erzeugt für die Ansicht Actuals vs vorhergesagt:

ggplot(val, aes(State, Value)) + geom_bar(stat = "identity", subset = .(variable == "estimate"), fill = "grey70") + geom_crossbar(aes(ymin = Value, ymax = Value), subset = .(variable == "actual")) 

, die zurückgibt:

alt text http://www.cerebralmastication.com/wp-content/uploads/2009/11/exp1.png

Aber es ist noch kein Pareto-Diagramm. Irgendwelche Tipps?

+0

Sie können dies tun, mit Basis Grafiken Par (neu) Trick von overplotting mit - gleichen Ansatz wie für die üblichen ‚Diagramm mit zwei Y-Achsen‘ Problem. Ggplot2 Ich kann nicht anders (noch, eines Tages bekomme ich vielleicht Zeit, es nachzuholen). –

+0

Ich versuche soooo schwer zu vermeiden, Basisgrafiken zu lernen. Ich bin fantastisch faul :) –

Antwort

15

Die Balken in ggplot2 sind nach der Reihenfolge der Ebenen im Faktor sortiert.

val$State <- with(val, factor(val$State, levels=val[order(-Value), ]$State)) 
+0

Das ist großartig! Genau das konnte ich nicht herausfinden. Vielen Dank! –

+4

Oder ein wenig prägnanter, ändern Sie Ihren ersten AES-Aufruf an: 'Aes (Reorder (State, Value), Wert)' – hadley

+2

Ich denke, Sie brauchen AES (Reorder (State, Value, Mittelwert), Value) - da sind zwei Werte für jeden Staat? – Andreas

23

Subsetting und Sortierung Ihrer Daten;

valact <- subset(val, variable=='actual') 
valsort <- valact[ order(-valact[,"Value"]),] 

Vom es ist nur einen Standard boxplot() mit einer sehr manuellen kumulativen Funktion auf:

op <- par(mar=c(3,3,3,3)) 
bp <- barplot(valsort [ , "Value"], ylab="", xlab="", ylim=c(0,1),  
       names.arg=as.character(valsort[,"State"]), main="How's that?") 
lines(bp, cumsum(valsort[,"Value"])/sum(valsort[,"Value"]), 
     ylim=c(0,1.05), col='red') 
axis(4) 
box() 
par(op) 

, die wie dieses

alt text http://dirk.eddelbuettel.com/misc/jdlong_pareto.png

aussehen sollte und es nicht einmal brauche den übertriebenen Trick, wie lines() glücklich die erste Handlung annotiert.

+0

Ich akzeptierte Changs Antwort, weil ich das wirklich mit ggplot machen wollte. Aber ich schulde dir immer noch ein Bier, um so eine tolle Antwort zu geben. –

+0

Nun, ich habe die Anforderungen von ggplot2 vermisst ... –

+0

Sie haben viel mehr durch die Antwort auf den Perato-Teil gegeben, als ich erwartet hatte! Meine Frage war grob stilisiert und ich hatte mich in eine Ecke eingeordnet, wo ggplot2 der einfachste Weg war. Was du mit der Basisgrafik gemacht hast, war wirklich cool. Danke noch einmal. –

3

Siehe auch das Paket qcc, das eine Funktion pareto.chart() hat. Sieht so aus, als ob es Basisgrafiken verwendet, also starte dein Kopfgeld für eine ggplot2-Lösung :-)

4

Mit einem einfachen Beispiel:

> data 
    PC1  PC2  PC3  PC4  PC5  PC6  PC7  PC8  PC9 PC10 
0.29056 0.23833 0.11003 0.05549 0.04678 0.03788 0.02770 0.02323 0.02211 0.01925 

barplot(data) tut Dinge richtig

die ggplot Äquivalent "sollte": qplot(x=names(data), y=data, geom='bar')

Aber das falsch Nachbestellungen/sortiert die alphabetisch Bars. .. denn so würde levels(factor(names(data))) bestellt werden.

Lösung: qplot(x=factor(names(data), levels=names(data)), y=data, geom='bar')

Puh!

1

Um die Dinge zu vereinfachen, lassen Sie uns nur die Schätzungen berücksichtigen.

estimates <- subset(val, variable == "estimate") 

Zuerst neu ordnen wir die Faktorstufen, so dass State s in absteigender Reihenfolge der Value aufgetragen sind.

estimates$State <- with(estimates, reorder(State, -Value)) 

In ähnlicher Weise ordnen wir den Datensatz neu an und berechnen einen kumulativen Wert.

estimates <- estimates[order(estimates$Value, decreasing = TRUE),] 
estimates$cumulative <- cumsum(estimates$Value) 

Jetzt sind wir bereit, die Handlung zu zeichnen. Der Trick, um eine Linie und einen Balken auf den gleichen Achsen zu erhalten, besteht darin, die Zustandsvariable (einen Faktor) in einen numerischen Wert umzuwandeln.

p <- ggplot(estimates, aes(State, Value)) + 
    geom_bar() + 
    geom_line(aes(as.numeric(State), cumulative)) 
p 

Wie in der Frage erwähnt, versucht, sie direkt neben zwei Pareto Plots von zwei variablen Gruppen zu ziehen, ist nicht ganz einfach. Sie wären wahrscheinlich besser dran Facettierung, wenn Sie mehrere Pareto-Plots möchten.

7

Ein traditionelles Pareto-Diagramm in ggplot2 .......

Entwickelt nach Cano, E. L., Moguerza, J. M. Lesen, & Redchuk, A. (2012). Six Sigma mit R. (G. Robert, K. Hornik, & G. Parmigiani, Hrsg.) Springer.

library(ggplot2);library(grid) 

counts <- c(80, 27, 66, 94, 33) 
defects <- c("price code", "schedule date", "supplier code", "contact num.", "part num.") 
dat <- data.frame(count = counts, defect = defects, stringsAsFactors=FALSE) 
dat <- dat[order(dat$count, decreasing=TRUE),] 
dat$defect <- factor(dat$defect, levels=dat$defect) 
dat$cum <- cumsum(dat$count) 
count.sum<-sum(dat$count) 
dat$cum_perc<-100*dat$cum/count.sum 

p1<-ggplot(dat, aes(x=defect, y=cum_perc, group=1)) 
p1<-p1 + geom_point(aes(colour=defect), size=4) + geom_path() 

p1<-p1+ ggtitle('Pareto Chart')+ theme(axis.ticks.x = element_blank(), axis.title.x = element_blank(),axis.text.x = element_blank()) 
p1<-p1+theme(legend.position="none") 

p2<-ggplot(dat, aes(x=defect, y=count,colour=defect, fill=defect)) 
p2<- p2 + geom_bar() 

p2<-p2+theme(legend.position="none") 

plot.new() 
grid.newpage() 
pushViewport(viewport(layout = grid.layout(2, 1))) 
print(p1, vp = viewport(layout.pos.row = 1,layout.pos.col = 1)) 
print(p2, vp = viewport(layout.pos.row = 2,layout.pos.col = 1)) 
0
freqplot = function(x, by = NULL, right = FALSE) 
{ 
if(is.null(by)) stop('Valor de "by" precisa ser especificado.') 
breaks = seq(min(x), max(x), by = by) 
ecd = ecdf(x) 
den = ecd(breaks) 
table = table(cut(x, breaks = breaks, right = right)) 
table = table/sum(table) 

intervs = factor(names(table), levels = names(table)) 
freq = as.numeric(table/sum(table)) 
acum = as.numeric(cumsum(table)) 

normalize.vec = function(x){ 
    (x - min(x))/(max(x) - min(x)) 
} 

dados = data.frame(classe = intervs, freq = freq, acum = acum, acum_norm = normalize.vec(acum)) 
p = ggplot(dados) + 
    geom_bar(aes(classe, freq, fill = classe), stat = 'identity') + 
    geom_point(aes(classe, acum_norm, group = '1'), shape = I(1), size = I(3), colour = 'gray20') + 
    geom_line(aes(classe, acum_norm, group = '1'), colour = I('gray20')) 

p 
}