【问题标题】:Creating a Pareto Chart with ggplot2 and R使用 ggplot2 和 R 创建帕累托图
【发布时间】:2010-12-16 16:07:42
【问题描述】:

我一直在努力研究如何使用 ggplot2 包在 R 中创建 Pareto Chart。在许多情况下,当制作条形图或直方图时,我们希望项目按 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 已排序,但输出如下所示:


(来源:cerebralmastication.com

Hadley 正确地指出,这会产生更好的图形来显示实际值与预测值:

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

返回:


(来源:cerebralmastication.com

但它仍然不是帕累托图。有什么建议吗?

【问题讨论】:

  • 您可以使用重叠绘图的 par(new) 技巧对基本图形执行此操作——与通常的“带有两个 y 轴的图表”问题的方法相同。 Ggplot2 我无能为力(但是,也许有一天我有时间赶上它)。
  • 我正在努力避免学习基础图形。我非常懒惰:)

标签: r graph ggplot2


【解决方案1】:

我们可以使用ggQC 包。

library(ggplot2)
library(ggQC)
Data4Pareto <- data.frame(
  KPI = c("Customer Service Time", "Order Fulfillment", "Order Processing Time",
          "Order Production Time", "Order Quality Control Time", "Rework Time",
          "Shipping"),
  Time = c(1.50, 38.50, 3.75, 23.08, 1.92, 3.58, 73.17)) 


ggplot2::ggplot(Data4Pareto, aes(x = KPI, y = Time)) +
 ggQC::stat_pareto(point.color = "red",
                   point.size = 3,
                   line.color = "black",
                   bars.fill = c("blue", "orange")) +
  theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust=0.5))

Source

【讨论】:

    【解决方案2】:

    对数据进行子集化和排序;

    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)
    

    应该是这样的


    (来源:eddelbuettel.com

    它甚至不需要过度绘图技巧,因为lines() 很高兴地注释了初始情节。

    【讨论】:

    • 我接受了 Chang 的回答,因为我真的很想用 ggplot 来做这件事。但我还是欠你一杯啤酒,因为你给出了这么棒的答案。
    • 您对 Perato 部分的回答比我预期的要多得多!我的问题非常程式化,我已经将自己编码到一个角落,使用 ggplot2 是最简单的出路。你对基本图形所做的事情真的很酷。再次感谢。
    • @DirkEddelbuettel -- 作为一个疯狂的后续行动,我想知道您是否可以修改您的答案以使其接受 facet_wrap?
    【解决方案3】:
    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
    }
    

    【讨论】:

      【解决方案4】:

      ggplot2中的传统帕累托图......

      阅读后开发 Cano, E. L.、Moguerza, J. M. 和 Redchuk, A. (2012)。六西格码与 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))
      

      【讨论】:

        【解决方案5】:

        为简化起见,我们只考虑估计值。

        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)
        

        现在我们准备绘制情节。在同一轴上获得一条线和条的技巧是将 State 变量(一个因子)转换为数字。

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

        如问题中所述,尝试绘制两个相邻变量组的两个帕累托图并不容易。如果您想要多个 Pareto 图,最好使用 facetting。

        【讨论】:

          【解决方案6】:

          举个简单的例子:

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

          呼!

          【讨论】:

            【解决方案7】:

            ggplot2 中的条形按因子中水平的顺序排列。

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

            【讨论】:

            • 太棒了!这正是我不知道该怎么做。谢谢!
            • 或者更简洁一点,将您的第一个 aes 调用更改为:` aes(reorder(State, Value), Value)`
            • 我认为你需要 aes(reorder(State, Value, mean), Value) - 因为每个状态都有两个值?
            【解决方案8】:

            另外,请参阅包qcc,它有一个函数pareto.chart()。看起来它也使用基本图形,所以开始赏金 ggplot2-solution :-)

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多