You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ggplot堆叠柱状图柱间添加差值(方差)条及对应数值标注

实现方法

步骤1:构造差值计算数据集

先从你已处理好的df.tmp中提取各分组总高度,计算相邻分组的差值与标注位置:

library(dplyr)
library(ggplot2)

diff_data <- df.tmp %>% 
  ungroup() %>% 
  select(group.id, total.by.x) %>% 
  distinct() %>% 
  mutate(
    next_group = lead(group.id),
    next_total = lead(total.by.x),
    x_mid = (group.id + next_group)/2,
    y_min = pmin(total.by.x, next_total),
    y_max = pmax(total.by.x, next_total),
    diff_val = abs(next_total - total.by.x)
  ) %>% 
  filter(!is.na(next_group))

步骤2:在原有绘图代码中新增差值条与标注图层

在你现有ggplot代码的geom_bar图层后,新增以下3类图层即可:

  • geom_segment绘制差值竖线与上下短横边
  • geom_text标注差值数值
    完整绘图代码如下:
ggplot(df.tmp, aes(x = group.id, y = values, fill = cat.Var)) +
  geom_bar(stat = "identity",position = "stack", width = 0.3)+
  # 新增差值条图层开始
  geom_segment(data = diff_data, aes(x = x_mid, xend = x_mid, y = y_min, yend = y_max), inherit.aes = FALSE) +
  geom_segment(data = diff_data, aes(x = x_mid - 0.05, xend = x_mid + 0.05, y = y_min, yend = y_min), inherit.aes = FALSE) +
  geom_segment(data = diff_data, aes(x = x_mid - 0.05, xend = x_mid + 0.05, y = y_max, yend = y_max), inherit.aes = FALSE) +
  geom_text(data = diff_data, aes(x = x_mid + 0.08, y = (y_min + y_max)/2, label = diff_val), inherit.aes = FALSE, size = 3) +
  # 新增差值条图层结束
  scale_fill_manual(values=c('#ff0000','#c8f464')) +
  scale_x_continuous(
    expand=c(0,0),
    limits = c(min(df.tmp$group.id)-0.5,max(df.tmp$group.id)+0.5),
    breaks = c(min(df.tmp$group.id)-0.5,
               unique(df.tmp$group.id),
               unique(df.tmp$group.id) + 0.5
    ),
    labels =
      c("",
        as.character(unique(df.tmp$x.axis.Var)),
        rep(c(""), length(unique(df.tmp$x.axis.Var)))
      )
  ) +
  theme(
    text = element_text(size = 5, color = "#4e4d47"),
    axis.text = element_text(size = 8, angle = 90, vjust = 0.5, hjust=1, color = "#4e4d47", face = "bold"),
    axis.text.y = element_text(margin = margin(r = 0.3, unit = "cm")),
    axis.ticks.x =
      element_line(color =
                     c("black",
                       rep(NA, length(unique(df.tmp$x.axis.Var))),
                       rep("black", length(unique(df.tmp$x.axis.Var))-1)
                     )
    ),
    axis.line = element_line(colour = "#4e4d47", size = 0.5),
    axis.ticks.length = unit(.15, "cm"),
    axis.title.x =       element_blank(),
    axis.title.y =       element_blank(),
    panel.background =   element_blank(),
    plot.margin =        unit(c(1, 1, 1, 1), "lines"),
    legend.text =        element_text(size = 10,
                                      color = "#4e4d47",
                                      face = "bold",
                                      margin = margin(l = 0.25, unit = "cm")
    ),
    legend.title =       element_blank()
  )

参数调整说明

  • 差值条短横边长度:修改geom_segment中的x_mid ± 0.05的数值,数值越大横边越长
  • 差值文字位置:修改geom_text中的x_mid + 0.08调整水平位置,修改size参数调整文字大小
  • 如果需要标注正负差值,去掉diff_val计算时的abs()函数即可

内容的提问来源于stack exchange,提问作者Fishza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 11:15:08