Création D'un graphique Pareto avec ggplot2 et R
j'ai eu du mal avec Comment faire un Diagramme De Pareto dans R en utilisant le paquet ggplot2. Dans de nombreux cas de faire un histogramme nous voulons que les éléments triés par l'axe des abscisses. Dans un graphique de Pareto nous voulons Les articles ordonnés Descendant Par la valeur dans l'axe des Y. Est-il un moyen d'obtenir ggplot pour tracer des articles commandés par la valeur de l'axe des Y? J'ai essayé de trier les données mais il semble que ggplot les réordonne.
Exemple:
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")
les données cadre val est trié, mais la sortie ressemble à ceci:
texte alternatif http://www.cerebralmastication.com/wp-content/uploads/2009/11/exp.png
<!-Hadley a fait remarquer à juste titre que cela produit un graphique bien meilleur pour montrer les données réelles par rapport aux prévisions:ggplot(val, aes(State, Value)) + geom_bar(stat = "identity", subset = .(variable == "estimate"), fill = "grey70") + geom_crossbar(aes(ymin = Value, ymax = Value), subset = .(variable == "actual"))
renvoie:
texte alternatif http://www.cerebralmastication.com/wp-content/uploads/2009/11/exp1.png
mais ce n'est toujours pas un diagramme de Pareto. Tout des conseils?
7 réponses
Les barres en ggplot2 sont commandés par l'ordre des niveaux du facteur.
val$State <- with(val, factor(val$State, levels=val[order(-Value), ]$State))
. et le tri de vos données;
valact <- subset(val, variable=='actual')
valsort <- valact[ order(-valact[,"Value"]),]
à Partir de là c'est juste une norme boxplot()
avec une fonction cumulative très manuelle sur le dessus:
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)
qui devrait ressembler à ceci
texte alternatif http://dirk.eddelbuettel.com/misc/jdlong_pareto.png
et il n'a même pas besoin de la overplotting truc comme lines()
annote heureusement l'intrigue initiale.
une carte traditionnelle de Pareto en ggplot2.......
développé après lecture Cano, E. L., Moguerza, J. M., & Redchuk, A. (2012). Six Sigma with 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))
Avec un exemple simple:
> 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)
fait les choses correctement
le ggplot équivalent "devrait être": qplot(x=names(data), y=data, geom='bar')
mais qui réarrange/trie incorrectement les barres par ordre alphabétique... parce que c'est comment levels(factor(names(data)))
serait ordonné.
Solution:qplot(x=factor(names(data), levels=names(data)), y=data, geom='bar')
Ouf!
Voir Aussi Le Paquet ccq qui a une fonction pareto.chart()
. On dirait qu'il utilise des graphismes de base aussi, alors démarrez votre bounty pour un ggplot2-solution: -)
pour simplifier les choses, considérons seulement les estimations.
estimates <- subset(val, variable == "estimate")
tout d'abord, nous réorganisons les niveaux de facteur, de sorte que State
s sont tracés en ordre décroissant de Value
.
estimates$State <- with(estimates, reorder(State, -Value))
de même, nous réorganisons l'ensemble de données et calculons une valeur cumulative.
estimates <- estimates[order(estimates$Value, decreasing = TRUE),]
estimates$cumulative <- cumsum(estimates$Value)
Maintenant, nous sommes prêts à dessiner le tracé. L'astuce pour obtenir une ligne et d'un bar sur les mêmes axes est de convertir la variable d'État (un facteur) pour être numérique.
p <- ggplot(estimates, aes(State, Value)) +
geom_bar() +
geom_line(aes(as.numeric(State), cumulative))
p
Comme mentionné dans la question, essayer de dessiner deux diagrammes de Pareto de deux groupes variables juste à côté de l'autre n'est pas très facile. Vous feriez mieux d'utiliser le facetting si vous voulez plusieurs parcelles de 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
}