rdplyrbar-chartfacet-gridstacked-bar-chart

In R, how to place error bars at each bar which is stacked, particularly when using facet_grid?


Here is one dataset

df=data.frame(
  cultivar = rep(c("CV1", "CV2"), each = 8L),
  part = rep(rep(c("DW1", "DW2"), 2), each = 4L),
  Light = rep(rep(c("Light1", "Light2"), 4), each = 2L),
  Treatment = rep(c("Treatment 1", "Treatment 2"), 8),
  DW_Mean = c(69.2825, 94.82, 57.8025, 90.7225, 26.6975, 37.3, 21.73, 28.3525, 58.825,
    79.45, 45.3225, 67.2425, 24.78, 32.2425, 16.8475, 24.9825
  ),
  DW_se = c(7.3890441138666, 12.3060777666972, 4.7905851678057, 5.91931355113637,
    5.10530830769961, 2.13571221531991, 1.87420205243014, 0.906838601957373,
    3.60502773914432, 7.59180918270913, 2.066044429177, 4.76078840634616,
    2.56271990926307, 1.23644904868741, 1.94433096891107, 2.04306295791393))

and I want to put error bars at each stacked bar. So I used this code.

   library(dplyr)
   library(ggplot2)

   dplyr::mutate(df, .by=cultivar, cume_y=cumsum(DW_Mean)) |>
        ggplot(aes(x=cultivar, y=DW_Mean, fill=part)) +
          geom_bar(stat="identity", position=position_stack(reverse=T), width=0.7, size=1) +
          geom_errorbar(aes(ymin=cume_y-DW_se, ymax=cume_y+DW_se),
                        position="identity", width=0.3) +
          scale_fill_manual(values = c("coral4", "grey45")) +
          scale_y_continuous(breaks = seq(0, 200, 50), limits = c(0, 200)) +
          facet_grid(~ Light ~ Treatment, scales = "free") +
          annotate("segment", x = 1, xend = 2, y = Inf, yend = Inf, color = "black", lwd = 1) +
          annotate("segment", y = 50, yend = 150, x = Inf, xend = Inf, color = "black", lwd = 1) +
          theme_classic(base_size = 18, base_family = "serif") +
          theme(legend.position = c(0.4, 0.9),
          legend.title = element_blank(),
          axis.line = element_line(linewidth = 0.5, colour = "black"),
          strip.background = element_rect(color = "white", linewidth = 0.5, linetype = "solid"))

Now, the error bars are misplaced. If I filter each variable (i.e., only Treatment 1 and Light 1) and create the stacked bar, I can place the error bars at the exact location of the stacked bar. However, when I use facet_grid(), the error bars are misplaced.

Could you please let me know how to solve this problem?

Thanks,

enter image description here


Solution

  • I think your code for geom_bar() and geom_errorbar() should be working fine. However, the code for generating cume_y variable might be problematic. I replace .by=cultivar with .by = c(Treatment, Light, cultivar) as in the following

    library(dplyr)
    library(ggplot2)
    
    df |>
      mutate(.by = c(Treatment, Light, cultivar), cume_y = cumsum(DW_Mean)) |>
      ggplot(aes(x = cultivar, y = DW_Mean, fill = part)) +
      geom_bar(stat = "identity", position = position_stack(reverse = T), width = 0.7, size = 1) +
      geom_errorbar(aes(ymin = cume_y - DW_se, ymax = cume_y + DW_se),
        position = "identity", width = 0.3
      ) +
      scale_fill_manual(values = c("coral4", "grey45")) +
      scale_y_continuous(breaks = seq(0, 200, 50), limits = c(0, 200)) +
      facet_grid(~Light ~ Treatment, scales = "free") +
      annotate("segment", x = 1, xend = 2, y = Inf, yend = Inf, color = "black", lwd = 1) +
      annotate("segment", y = 50, yend = 150, x = Inf, xend = Inf, color = "black", lwd = 1) +
      theme_classic(base_size = 18, base_family = "serif") +
      theme(
        legend.position = c(0.4, 0.9),
        legend.title = element_blank(),
        axis.line = element_line(linewidth = 0.5, colour = "black"),
        strip.background = element_rect(color = "white", linewidth = 0.5, linetype = "solid")
      )
    

    enter image description here