在R语言中使用facet_grid时如何为堆叠柱状图添加正确误差棒
R语言堆叠柱状图分面后误差棒错位问题解决
问题描述
绘制堆叠柱状图并为每个堆叠柱添加误差棒时,单独筛选单个Treatment和Light子集绘制误差棒位置正确,但使用facet_grid后误差棒出现错位,数据集及原代码如下:
数据集
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))
原代码
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"))
问题原因
计算累积值cume_y时仅按cultivar分组,未考虑分面变量Light和Treatment,导致不同分面下的累积值被错误合并,进而造成误差棒位置错位。
解决方案
修改mutate的分组条件,将Light和Treatment也加入分组,确保每个分面内的堆叠累积值独立计算:
library(dplyr) library(ggplot2) # 调整分组条件,加入分面变量Light和Treatment dplyr::mutate(df, .by=c(cultivar, Light, Treatment), 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"))
补充说明
- 每个分面对应
Light和Treatment的唯一组合,只有将这两个变量与cultivar共同作为分组依据,才能保证每个分面内的堆叠柱累积值计算准确,误差棒才能对应到正确的堆叠块顶部位置。 - 代码中
position_stack(reverse=T)反转了堆叠顺序,当前数据集的part顺序与反转后的堆叠顺序匹配,因此无需额外调整cumsum的排序逻辑。
内容的提问来源于stack exchange,提问作者J.K Kim
相关产品推荐
相关产品推荐

