Создание диаграммы Парето с помощью ggplot2 и R

StackOverflow https://stackoverflow.com/questions/1735540

  •  20-09-2019
  •  | 
  •  

Вопрос

Я долго ломал голову над тем, как сделать Диаграмма Парето в R используется пакет ggplot2.Во многих случаях при создании столбчатой диаграммы или гистограммы мы хотим, чтобы элементы были отсортированы по оси X.На диаграмме Парето мы хотим, чтобы элементы были упорядочены по убыванию значения по оси Y.Есть ли способ заставить ggplot отображать элементы, упорядоченные по значению на оси Y?Сначала я попытался отсортировать фрейм данных, но, похоже, ggplot переупорядочивает их.

Пример:

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 отсортирован, но выходные данные выглядят примерно так:

alt text
(источник: cerebralmastication.com)

Хэдли правильно отметил, что это дает гораздо лучшую графику для отображения фактических данных по сравнению спредсказанный:

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

который возвращает:

alt text
(источник: cerebralmastication.com)

Но это все равно не диаграмма Парето.Есть какие-нибудь советы?

Это было полезно?

Решение

Столбцы в ggplot2 упорядочены по порядку уровней фактора.

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

Другие советы

Подмножество и сортировка ваших данных;

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

Отсюда это просто стандарт boxplot() с очень ручной накопительной функцией сверху:

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)

который должен выглядеть так

alt text
(источник: eddelbuettel.com)

и для этого даже не нужен трюк с перезаписью, поскольку lines() с радостью комментирует первоначальный сюжет.

Традиционная диаграмма Парето в ggplot2.......

Разработано после прочтения Кано, Э.Л., Могерза, Дж.М., & Редчук, А.(2012).Шесть Сигм с R.(G.Роберт, К.Хорник и Дж.Пармиджани, ред.) Спрингер.

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

На простом примере:

 > 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) делает все правильно

эквивалент ggplot «должен быть»: qplot(x=names(data), y=data, geom='bar')

Но это неправильно переупорядочивает/сортирует столбцы в алфавитном порядке...потому что вот так levels(factor(names(data))) был бы заказан.

Решение: qplot(x=factor(names(data), levels=names(data)), y=data, geom='bar')

Уф!

Также смотрите пакет qcc который имеет функцию pareto.chart().Похоже, он тоже использует базовую графику, так что начните награду за решение ggplot2 :-)

Для упрощения давайте просто рассмотрим только оценки.

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

Сначала мы переупорядочим уровни факторов так, чтобы States представлены в порядке убывания Value.

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

Аналогичным образом мы переупорядочиваем набор данных и вычисляем совокупное значение.

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

Теперь мы готовы нарисовать сюжет.Хитрость в том, чтобы расположить линию и столбец на одних и тех же осях, заключается в преобразовании переменной состояния (коэффициента) в числовое значение.

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

Как упоминалось в вопросе, попытаться нарисовать два графика Парето для двух групп переменных рядом друг с другом не очень легко.Вероятно, вам лучше использовать фасетирование, если вам нужно несколько графиков Парето.

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
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top