R用小提琴曲线替换条形图中的一个条形

时间:2017-01-06 23:37:09

标签: r ggplot2 layout bar-chart violin-plot

我正在使用条形图比较3个模型的结果,用于某组参数。条形图是必要的,因为我只有2个模型的中位数和可信区间。我想用小提琴图替换或覆盖每组的第3个条(显示每组的模型3参数的边缘后部)。我很乐意使用base R,ggplot或其他任何有效的东西!

我到目前为止所尝试的简化版本如下:

library(ggplot2)
library(plyr)

## Data
params <- paste0("param", 1:3)
medians <- data.frame(value = c(seq(0.1,0.6, by = 0.1), rep(0, 3)),
                      model = rep(c("M1", "M2", "M3"), each = 3),
                      parameter = rep(paste0("param", 1:3), 3))
m3_posterior <- data.frame(value = runif(900, 0.2, 0.7), 
                           model = "M3", 
                           parameter = rep(params, each = 3)) 
m3_stats <- ddply(m3_posterior, .(parameter), summarize,
                 lower = quantile(value, 0.025), 
                 upper = quantile(value, 0.975) ) 
confs <- data.frame(lower = c(seq(0.05, 0.55, by = 0.1), m3_stats$lower),
                    upper = c(seq(0.15, 0.65, by = 0.1), m3_stats$upper),
                    model = rep(c("M1", "M2", "M3"), each = 3),
                    parameter = rep(params, 3))                        

## plotting code
transparent_theme <- theme(
 axis.title.x = element_blank(),
 axis.title.y = element_blank(),
 axis.text.x = element_blank(),
 axis.text.y = element_blank(),
 axis.ticks = element_blank(),
 panel.grid = element_blank(),
 axis.line = element_blank(),
 panel.background = element_rect(fill = "transparent",colour = NA),
 plot.background = element_rect(fill = "transparent",colour = NA))

print_list <- list()
for (param in 1 : length(params)) {
  gg_medians <- subset(medians, parameter == params[param])
  gg_confs <- subset(confs, parameter == params[param])
  gg_post <- subset(m3_posterior, parameter == params[param])

  p1 <- ggplot(gg_medians, aes(model, value)) + 
        geom_bar(stat="identity", fill = "white", colour = "black") +
        geom_errorbar(data = gg_confs, 
                      aes(y=upper, ymax=upper, ymin=lower)) +
        scale_y_continuous(limits=c(0,1)) + labs(x=params[param])

  p2 <- ggplot(gg_post, aes(parameter, value)) +
        geom_violin(width=1.5, fill = NA)+
        transparent_theme +
        geom_errorbar(data = subset(gg_confs, model == "M3"),
            aes(y=upper, ymax=upper, ymin=lower)) +
        scale_y_continuous(limits=c(0,1)) + labs(x=params[param])

  if (param > 1 ) {
    p1 <- p1 + theme(axis.title.y=element_blank(),
                     axis.text.y=element_blank(),
                     axis.ticks.y=element_blank())
    p2 <- p2 + theme(axis.title.y=element_blank(),
               axis.text.y=element_blank(),
               axis.ticks.y=element_blank())
  }
  p2_grob <- ggplotGrob(p2)

  print_list[[param]] <- p1 + annotation_custom(grob = p2_grob, 
                           xmin = 2.5, xmax = 3.5,
                           ymin = -0.0665, ymax = 1.061)
}

lay_out = function(...) {
  x <- list(...)
  n <- max(sapply(x, function(x) max(x[[2]])))
  p <- max(sapply(x, function(x) max(x[[3]])))
  grid::pushViewport(grid::viewport(layout = grid::grid.layout(n, p)))

  for (i in seq_len(length(x))) {
    print(x[[i]][[1]], vp = grid::viewport(
    layout.pos.row = x[[i]][[2]],
    layout.pos.col = x[[i]][[3]]))
  }
}
lay_out(list(print_list[[1]], 1, 1),
    list(print_list[[2]], 1, 2),
    list(print_list[[3]], 1, 3))

我遇到的主要问题是:

  • 将小提琴情节grob与底层条形图对齐(我基本上使用猜测并检查数字)

  • 保持每个图的绘图区域相同,而第一个图上只有y轴

enter image description here

1 个答案:

答案 0 :(得分:0)

您希望m3中的两个错误栏在垂直和水平方向上对齐。

水平对齐 - 将各种轴元素设置为空白的方法并不常用 - 轴上剩余的空间很小。我发现从p2&gt; gtable中选择绘图面板更容易,然后将其插入p1。

垂直对齐 - 将ymin和ymax设置为-Inf和Inf应该处理垂直对齐,提供两个图的限制是相同的。我已将小提琴图中错误栏的颜色更改为红色,以便更容易看到对齐(或错位)。

使三个绘图面板的宽度相同 - 从print_list [[1]]剥离轴材料,然后使三个面板的宽度为单位(1,&#34; npc&#34; )。此外,您可以从print_list [[2]]和print_list [[3]]中选择绘图面板,因此无需将轴元素设置为空白。我发现使用gtable设置布局更容易。

此外,您收到一条警告消息,因为geom_errorbar没有美学效果。并且,在m3处,在y = 0处得到一条线,因为条形高度设置为零。如果您不想要该线,请将条形高度设置为NA。

<a href=""></a>