Domanda

Ho lottato con il modo di fare una Pareto Grafico in R utilizzando il pacchetto ggplot2 . In molti casi, quando si effettua un grafico a barre o istogramma vogliamo elementi ordinati per l'asse X. In un diagramma di Pareto vogliamo che gli articoli ordinati decrescente in base al valore nell'asse Y. C'è un modo per ottenere ggplot per tracciare articoli ordinati in base al valore nell'asse Y? Ho provato classificare il frame di dati prima ma sembra ggplot riordina.

Esempio:

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

Val frame di dati vengono ordinati, ma l'uscita è simile al seguente:

alt text
(fonte: cerebralmastication.com )

Hadley ha giustamente osservato che questo produce una grafica molto migliore per mostrare valori effettivi vs. predetto:

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

che restituisce:

alt text
(fonte: cerebralmastication.com )

Ma non è ancora un diagramma di Pareto. Eventuali suggerimenti?

È stato utile?

Soluzione

Le barre in ggplot2 sono ordinate per l'ordinamento dei livelli del fattore.

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

Altri suggerimenti

Impostazione secondaria e l'ordinamento dei dati;

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

Da lì è solo un boxplot() di serie con una funzione cumulativa molto manuale sulla parte superiore:

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)

che dovrebbe assomigliare a questo

alt text
(fonte: eddelbuettel.com )

e non ha nemmeno bisogno il trucco overplotting come lines() annota felicemente la trama iniziale.

Un grafico tradizionale Pareto ggplot2 .......

Sviluppato dopo la lettura Cano, E. L., Moguerza, J. M., & Redchuk, A. (2012). Six Sigma con R. (G. Robert, K. Hornik, & G. Parmigiani, Eds.) 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))

Con un semplice esempio:

 > 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) fa le cose in modo corretto

il ggplot equivalente "dovrebbe essere": qplot(x=names(data), y=data, geom='bar')

Ma che riordina gli errato / ordina la barre in ordine alfabetico ... perché è così che levels(factor(names(data))) sarebbe stato ordinato.

Soluzione: qplot(x=factor(names(data), levels=names(data)), y=data, geom='bar')

Accidenti!

Inoltre, si rimanda al foglio qcc che ha una funzione pareto.chart(). Sembra che utilizza la grafica di base troppo, in modo da iniziare la vostra generosità per un ggplot2 soluzione: -)

Per semplificare le cose, facciamo solo prendere in considerazione solo le stime.

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

Per prima cosa riordinare i livelli dei fattori, in modo che States sono tracciate in ordine di Value decrescente.

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

Allo stesso modo, abbiamo riordinare i set di dati e calcolare un valore cumulativo.

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

Ora siamo pronti per disegnare la trama. Il trucco per ottenere una linea e bar sugli stessi assi è di convertire la variabile Stato (fattore) per essere numerico.

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

Come indicato nella domanda, cercando di disegnare due lotti di Pareto di due gruppi di variabili accanto gli uni agli altri non è molto facile. Si sarebbe probabilmente essere meglio utilizzare sfaccettatura se si vuole più grafici di Pareto.

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
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top