使用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
相关产品推荐
相关产品推荐

