Pergunta

Eu tenho lutado para saber como fazer um Diagrama de pareto em R usando o pacote ggplot2.Em muitos casos, ao criar um gráfico de barras ou histograma, queremos que os itens sejam classificados pelo eixo X.Em um Gráfico de Pareto, queremos os itens ordenados de forma decrescente pelo valor no eixo Y.Existe uma maneira de fazer com que o ggplot plote itens ordenados pelo valor no eixo Y?Tentei classificar o quadro de dados primeiro, mas parece que o ggplot os reordena.

Exemplo:

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

o quadro de dados val é classificado, mas a saída é semelhante a esta:

alt text
(fonte: cerebralmastication.com)

Hadley apontou corretamente que isso produz um gráfico muito melhor para mostrar valores reais vs.previsto:

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

que retorna:

alt text
(fonte: cerebralmastication.com)

Mas ainda não é um gráfico de Pareto.Alguma dica?

Foi útil?

Solução

As barras no GGPlot2 são ordenadas pela ordem dos níveis no fator.

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

Outras dicas

Subconjuntar e classificar seus dados;

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

De lá é apenas um padrão boxplot() com uma função cumulativa muito manual no topo:

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)

o que deve ser assim

alt text
(fonte: eddelbuettel.com)

E nem precisa do truque de sobrecarga como lines() Anuncia felizmente o enredo inicial.

Um gráfico tradicional de pareto em ggplot2 .......

Desenvolvido após ler Cano, El, Moguerza, JM, & Redchuk, A. (2012). Six Sigma com R. (G. Robert, K. Hornik e G. Parmigiani, orgs.) 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))

Com um exemplo simples:

 > 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) faz as coisas corretamente

O equivalente a GGPlot "deve ser": qplot(x=names(data), y=data, geom='bar')

Mas isso se reordoma/classifica incorretamente as barras em ordem alfabética ... porque é assim levels(factor(names(data))) seria ordenado.

Solução: qplot(x=factor(names(data), levels=names(data)), y=data, geom='bar')

Ufa!

Além disso, veja o pacote QCC que tem uma função pareto.chart(). Parece que também usa gráficos básicos, então comece sua recompensa para uma solução GGPlot2 :-)

Para simplificar as coisas, vamos considerar apenas as estimativas.

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

Primeiro reordenamos os níveis dos fatores, de modo que States são plotados em ordem decrescente de Value.

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

Da mesma forma, reordenamos o conjunto de dados e calculamos um valor cumulativo.

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

Agora estamos prontos para desenhar o enredo.O truque para obter uma linha e uma barra nos mesmos eixos é converter a variável State (um fator) em numérica.

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

Conforme mencionado na pergunta, tentar desenhar dois gráficos de Pareto de dois grupos de variáveis ​​um ao lado do outro não é muito fácil.Provavelmente seria melhor usar a facetação se quiser vários gráficos 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
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top