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?

19
demandé sur JD Long 2009-11-14 23:46:51

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))
15
répondu Jonathan Chang 2009-11-15 00:37:09

. 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.

23
répondu Dirk Eddelbuettel 2009-11-14 21:20:44

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))
7
répondu Isaiah 2012-10-11 12:28:41

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!

4
répondu Yannick Wurm 2010-03-30 18:47:15

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

3
répondu Dirk Eddelbuettel 2009-11-14 22:03:28

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.

1
répondu Richie Cotton 2010-09-28 10:09:15
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
}
0
répondu Fernando 2013-02-21 19:49:14