如何在ggplot瀑布图中为所有条形添加对应误差棒?
解决瀑布图中为每个条形添加对应误差棒的问题
我明白你想要的效果——每个年份里,每个Affil的正负条形都要有自己对应的误差棒。你当前的代码里,同一Affil的正负值被geom_bar默认叠加了,而且误差棒没有正确绑定到每个单独的条形。这里有个清晰的解决方案:
第一步:给数据添加区分正负条形的标识
首先我们需要给数据加一列,标记每个值是正还是负,这样ggplot能识别出每个单独的条形:
library(dplyr) library(ggplot2) set.seed(100) # 原始数据构造 df<-tibble(Year= c(2001, 2001, 2001, 2001, 2002, 2002, 2002, 2002, 2003, 2003, 2003, 2003), Vals = abs(rnorm(12)*5), Affil = as.factor(c(1,2,1,2,1,2,1,2,1,2,1,2)), SD=rnorm(12, 1, 0.5)) df[c(T, T, F, F),]$Vals <- -(df[c(T, T, F, F),]$Vals) # 添加正负标识列 df <- df %>% mutate(Sign = ifelse(Vals < 0, "Negative", "Positive"), # 创建组合分组,让ggplot识别每个单独的条形 BarGroup = interaction(Affil, Sign))
第二步:绘制带对应误差棒的瀑布图
现在我们可以用BarGroup作为分组依据,让每个条形(包括正负)都单独显示,并绑定对应的误差棒:
p <- ggplot(data = df, aes(x = Year, y = Vals, group = BarGroup, fill = Affil)) + # 用position_dodge让同一年份的条形并排,宽度和误差棒保持一致 geom_bar(stat = "identity", position = position_dodge(width = 0.9)) + # 误差棒的position要和条形的dodge宽度匹配,确保一一对应 geom_errorbar(aes(ymin = Vals - SD, ymax = Vals + SD), width = 0.2, position = position_dodge(width = 0.9)) + theme_bw(base_size = 16) + geom_hline(aes(yintercept = 0), size = 1.25) + # 可选:用透明度区分正负条形,更直观 scale_alpha_manual(values = c(0.7, 1)) + aes(alpha = Sign) p
如果你想要同一Affil的正负条形在同一位置(上下分布)
如果更倾向于同一Affil的正负条形在年份的同一x位置(一个在0轴下方,一个在上方),可以调整x轴为Year和Affil的组合:
df <- df %>% mutate(XLabel = interaction(Year, Affil)) p <- ggplot(data = df, aes(x = XLabel, y = Vals, fill = Sign)) + geom_bar(stat = "identity", position = "identity") + geom_errorbar(aes(ymin = Vals - SD, ymax = Vals + SD), width = 0.2) + theme_bw(base_size = 16) + geom_hline(aes(yintercept = 0), size = 1.25) + # 自定义x轴标签,让年份和Affil清晰显示 scale_x_discrete(labels = function(x) { parts <- strsplit(as.character(x), "\\.") paste("Year", sapply(parts, `[`, 1), "\nAffil", sapply(parts, `[`, 2)) }) + labs(x = "Year & Affiliation") p
这样每个Affil的正负条形都会有自己独立的误差棒,完全符合你的需求。
内容的提问来源于stack exchange,提问作者DotPi
相关产品推荐
相关产品推荐

