条形图的误差条仅在一个方向,但最后一个在相反方向

Error bars for barplot only in one direction, but for the last one in the opposite direction

这个很有用post shows how to display error bars in one direction only with ggplot. To do this, the geom_errorbar function is modified as follows (as proposed by Sean Hughes):

geom_uperrorbar <- function(mapping = NULL, data = NULL,
   stat = "identity", position = "identity",
   ...,
   na.rm = FALSE,
   show.legend = NA,
   inherit.aes = TRUE) {
   layer(
      data = data,
      mapping = mapping,
      stat = stat,
      geom = GeomUperrorbar,
      position = position,
      show.legend = show.legend,
      inherit.aes = inherit.aes,
      params = list(
         na.rm = na.rm,
         ...
      )
   )
}

GeomUperrorbar <- ggproto("GeomUperrorbar", Geom,
   default_aes = aes(colour = "black", size = 0.5, linetype = 1, width = 0.5,
      alpha = NA),

   draw_key = draw_key_path,
required_aes = c("x", "y", "ymax"),

   setup_data = function(data, params) {
      data$width <- data$width %||%
         params$width %||% (resolution(data$x, FALSE) * 0.9)

      transform(data,
         xmin = x - width / 2, xmax = x + width / 2, width = NULL
      )
   },draw_panel = function(data, panel_scales, coord, width = NULL) {
      GeomPath$draw_panel(data.frame(
         x = as.vector(rbind(data$xmin, data$xmax, NA, data$x,   data$x)),
         y = as.vector(rbind(data$ymax, data$ymax, NA, data$ymax, data$y)),
         colour = rep(data$colour, each = 5),
         alpha = rep(data$alpha, each = 5),
         size = rep(data$size, each = 5),
         linetype = rep(data$linetype, each = 5),
         group = rep(1:(nrow(data)), each = 5),
         stringsAsFactors = FALSE,
         row.names = 1:(nrow(data) * 5)
      ), panel_scales, coord)
   }
)


"%||%" <- function(a, b) {
   if (!is.null(a)) a else b
} 

但现在我遇到了最后一根柱线为负的情况。因此,最后一个柱的误差柱必须朝另一个方向移动。有谁知道这是如何工作的?

这是一个可重现的例子:

df <- data.frame(trt = factor(c(1, 1, 2, 2)), resp = c(1, 5, 3, -2),
                 group = factor(c(1, 2, 1, 2)), se = c(0.1, 0.3, 0.3, 0.2))
df2 <- df[c(1,3), ]

limits <- aes(ymax = resp + se, ymin = resp - se)
dodge <- position_dodge(width = 0.9)

p <- ggplot(df, aes(fill = group, y = resp, x = trt))
p + geom_bar(position = dodge, stat = "identity") +
  geom_errorbar(limits, position = dodge, width = 0.25)

链接问题中的解决方案实际上会产生这个结果。您只需要确保在条形向下时减去而不是添加标准误差:

limits <- aes(ymax = resp + se * sign(resp))

现在您的绘图代码几乎没有改变:

dodge  <- position_dodge(width = 0.9)

ggplot(df, aes(fill = group, y = resp, x = trt)) +
  geom_bar(position = dodge, stat = "identity") +
  geom_uperrorbar(limits, position = dodge, width = 0.25)