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

使用ggbrace为ggplot分组百分比堆叠柱状图添加垂直大括号

堆叠柱状图添加分组大括号的解决方法

需求说明

要给按年龄组划分的家庭类型百分比堆叠柱状图添加大括号:

  • 图表共4个年龄组柱子,每个柱子包含7个家庭类型填充类别
  • 仅给最后一个柱子添加3个大括号,分别对应3个分组:覆盖4个、2个、1个填充类别

遇到的问题

使用ggbrace包的geom_brace()时出现两个问题:

  • 继承数据方式:所有柱子都出现线条,bend参数未生成大括号,仅缩短线条
  • 手动设置方式:仅输入y值无显示,添加bend参数后仅生成对应长度的线条,仍无大括号

解决思路

geom_brace()需要明确指定大括号的起始和结束坐标,不能直接继承原数据的映射(否则会为每一行数据生成一个brace)。需先计算最后一个柱子各分组的y轴范围,再逐个定义大括号的位置。

步骤1:计算最后一个年龄组的累计百分比

提取最后一个年龄组(agegroup=4)的数据,计算每个家庭类型的累计y轴位置,确定分组的上下边界:

library(dplyr)
library(ggplot2)
library(ggbrace)

# 提取最后一个年龄组的数据并计算累计百分比
last_group <- hhtype_by_agegroup_proptable %>%
  filter(agegroup == 4) %>%
  arrange(hh_type) %>%
  mutate(cum_pct = cumsum(percentage),
         prev_cum_pct = lag(cum_pct, default = 0))

# 定义分组边界:假设分组为[1-4], [5-6], [7]
group1_y_start <- last_group$prev_cum_pct[1]
group1_y_end <- last_group$cum_pct[4]

group2_y_start <- last_group$prev_cum_pct[5]
group2_y_end <- last_group$cum_pct[6]

group3_y_start <- last_group$prev_cum_pct[7]
group3_y_end <- last_group$cum_pct[7]

步骤2:绘制图表并添加大括号

在绘图时,为每个大括号指定x和xend(最后一个柱子的右侧位置,比如4.2),y和yend对应分组的上下边界,同时设置rotate=90让大括号垂直显示:

# 基础绘图
p <- ggplot(hhtype_by_agegroup_proptable, aes(x=as.factor(agegroup), y=percentage, fill=hh_type)) +
  geom_bar(position="fill", stat="identity", width=0.4) +
  scale_y_continuous(labels=scales::percent_format(), n.breaks=10, minor_breaks=seq(0,1,0.05)) +
  scale_x_discrete(labels=c("18 to 19", "20 to 24", "25 to 29", "30 to 34")) +
  labs(x="年龄组", y="百分比", fill="家庭类型") +
  theme_minimal()

# 添加3个大括号及标签
p +
  # 第一个大括号:覆盖4个类别
  geom_brace(aes(x=4.2, xend=4.2, y=group1_y_start, yend=group1_y_end),
             rotate=90, bend=0.05, color="red", size=1) +
  geom_text(aes(x=4.4, y=(group1_y_start+group1_y_end)/2), label="分组1(4个类别)", color="red") +
  # 第二个大括号:覆盖2个类别
  geom_brace(aes(x=4.2, xend=4.2, y=group2_y_start, yend=group2_y_end),
             rotate=90, bend=0.05, color="blue", size=1) +
  geom_text(aes(x=4.4, y=(group2_y_start+group2_y_end)/2), label="分组2(2个类别)", color="blue") +
  # 第三个大括号:覆盖1个类别
  geom_brace(aes(x=4.2, xend=4.2, y=group3_y_start, yend=group3_y_end),
             rotate=90, bend=0.05, color="green", size=1) +
  geom_text(aes(x=4.4, y=(group3_y_start+group3_y_end)/2), label="分组3(1个类别)", color="green")

关键说明

  • 必须明确指定x、xend、y、yend参数,避免继承原数据的映射,否则会为每一行数据生成brace
  • rotate=90让大括号垂直显示,适配堆叠柱状图的y轴方向
  • bend参数控制大括号的弯曲程度,可根据需求调整(比如0.03-0.08)
  • 若需自定义分组,只需调整group1_y_start、group1_y_end等变量的取值即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 15:32:16