如何将摘要信息添加到geom_boxplot

时间:2014-05-31 12:31:49

标签: r ggplot2

我一直在使用R / ggplot2成功生成与我公司使用的商业工具生成的图形非常接近的图形。但是我有一些功能无法实现到使用R生成的箱图。

  1. 图表底部的摘要“表格”,显示中位数,计数,异常值等项目。
  2. 显示条带文本,以便删除重复的标签。
  3. 示例R代码:

    library(ggplot2)
    library(data.table)
    library(reshape2)
    library(grid)
    
    # create dataset
    dt <- data.table(mpg)
    
    # melt the data table
    dtm <- data.table(
      melt(data=dt,
           id.vars=c("manufacturer","model","displ","year","cyl","trans","drv","fl","class"),
           variable.name="mode", value.name="mpg"))
    write.csv(dtm,file="dtm.csv",row.names=F)
    
    # draw some plots
    p <- ggplot(dtm, aes(x=mode,y=mpg)) +
      geom_boxplot(aes(fill=mode), varwidth=F) +
      facet_grid( ~ manufacturer + year ) +
      theme_bw() +
      theme(panel.margin=unit(0,"mm"), panel.grid=element_blank()) +
      theme(axis.text.x=element_blank(), axis.title.x=element_blank()) +
      theme(legend.position="bottom") +
      coord_cartesian(ylim=c(0,50))
    p
    
    ggsave(plot=p, filename='ddtm_r.png', dpi=72, width=16, height=8)
    

    R生成的输出在这里,

    R/ggplot2 generated boxplot

    商业工具生成的同一箱图在这里,

    boxplot generated by commercial tool

    正如您所看到的那样,图表中的数据是理想的(如预期的那样),但是在商业版本中可以更好地组织条带标题,我也可以在图表的底部添加汇总表。

    R中有什么方法可以做类似的事情吗?

    谢谢&amp;的问候,

    Derric

    更新时间:2014年6月7日

    根据同事和在线帮助的建议,我现在能够绘制包含箱线图的图表,其中汇总表附加在箱线图的底部。主要思想是从boxplot grob中提取面板信息,然后使用它生成文本表,然后使用两个grobs重绘绘图。必须删除原始箱图的图例才能获得正确的右侧对齐。

    修改后的R代码如下,

    # load the libraries
    library(grid)
    library(gridExtra)
    library(data.table)
    library(reshape2)
    library(ggplot2)
    library(gtable)
    library(plyr)
    
    # create dataset
    dt <- data.table(mpg)
    
    # melt the data table
    dtm <- data.table(
      melt(data=dt,
            id.vars=c("manufacturer","model","displ","year","cyl","trans","drv","fl","class"),
           variable.name="mode", value.name="mpg"))
    #write.csv(dtm,file="dtm.csv",row.names=F)
    
    # draw some plots
    p1 <- ggplot(dtm, aes(x=factor(year),y=mpg)) +
      geom_boxplot(aes(fill=factor(year)), varwidth=F) +
      facet_grid( ~ manufacturer + mode ) +
      theme_bw() +
      theme(panel.margin=unit(0,"lines"), 
            panel.grid=element_blank(),
            strip.text=element_text(angle=90),
            axis.text.x=element_blank(), 
            axis.title.x=element_blank(),
            axis.ticks.x=element_blank(),
            plot.margin=unit(c(0,0,0,0),"lines"),
            legend.position="right") +
      coord_cartesian(ylim=c(0,50)) +
      xlab(NULL) 
    
    # deconstruct the plot p1
    pb <- ggplot_build(p1)
    # pb has three groups; data, panel and plot
    pb.data <- pb$data
    # pb.data[[1]] is a data.frame
    pb.data.df <- pb.data[[1]]
    # melt the pb.data.df
    pb.data.dt <- data.table(pb.data.df)
    #pb.data.dt[,':='(outliers=NULL)]
    pb.data.dtm <- melt(data=pb.data.dt,
                        #id.vars=c("x","PANEL"),
                        measure.vars=c("middle","lower","upper"),
                        variable.name="mode",
                        value.name="value")
    
    p2 <- ggplot(pb.data.dtm, aes(x=factor(x),y=factor(mode),label=format(value,nsmall=1))) +
      geom_text(size=3.0, angle=90, hjust=0.5) + facet_grid(~ PANEL) +
      theme_bw() +
      scale_y_discrete() +
      theme(panel.margin=unit(0,"lines"),
        panel.grid=element_blank(),
        panel.border=element_rect(), 
        legend.position="right",
        axis.text.x=element_blank(),
        axis.text.y=element_text(angle=0),
        axis.ticks=element_blank(),
        strip.text=element_blank(),
        strip.background=element_blank(),
        plot.margin=unit(c(0,0,0,0),"lines")
        ) +
      xlab(NULL) + ylab(NULL)
    
    # a function to extract the legend from the grob
    g_legend <- function(a.gplot) {
      tmp <- ggplotGrob(a.gplot)
      leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
      legend <- tmp$grobs[[leg]]
      legend
    }
    legend1 <- g_legend(p1)
    pa <- arrangeGrob((p1 + theme(legend.position='none')), legend1,
                 (p2 + theme(legend.position='none')), 
                 ncol=2, nrow=2, 
                 heights=c(50/60,10/60), widths=c(95/100,5/100))
    ggsave(plot=pa, filename='dtm_r.png',dpi=72,height=10,width=18)
    

    此脚本现在为我提供了如下所示的图表,

    Boxplot with summary table below it

    我对此图表的问题是面板在左侧略微错位。关于如何对齐面板的左手侧和右手侧的任何建议?

    谢谢,

1 个答案:

答案 0 :(得分:0)

我认为你应该只使用一个方面级别,而是将年份包含在传递给&#39; fill&#39;的分组参数中:

 p <- ggplot(dtm, aes(x=mode,y=mpg)) +
  geom_boxplot(aes(fill=interaction(mode,year) ), varwidth=F) +
  facet_grid( ~ manufacturer ) +
  theme_bw() +
  theme(panel.margin=unit(0,"mm"), panel.grid=element_blank()) +
  theme(axis.text.x=element_blank(), axis.title.x=element_blank()) +
  theme(legend.position="bottom") +
  coord_cartesian(ylim=c(0,50))

 p

品牌之间的分歧更加明显。此外,您可以明确地修改主题参数,以便品牌名称完全可见:

png(width=650) ; p <- p + theme(strip.text.x = element_text(size=8, angle=75)); 
print(p); dev.off()

enter image description here

如果你比较这些图,我认为很明显,我创建的图以更容易理解的方式传达信息。 1999年和2008年每加仑英里之间的比较更容易让观众在每个制造商的内部看到#。颜色有所帮助,方面划分只处于最高水平&#34;这允许适当的组内比较。