R ggplot2堆叠条形图添加柱端总计值标签的实现方法
问题原因
你之前无法把总标签放到正确位置,核心是两个细节没处理对:
- 用了
coord_flip()把纵向图转成横向条形图后,坐标轴映射逻辑变了:原本控制垂直位置的vjust、nudge_y不再控制柱端方向的偏移,你之前写的nudge_y=10直接把标签甩到了绘图区外;同时总标签层没有取消主图层的fill映射继承,分组逻辑冲突,位置计算直接错位。 - 原代码y轴上限设为0.6,柱末端的标签会被坐标轴边界截断,没有预留足够的显示空间。
修正方案
不需要改你之前的基础数据和总表计算逻辑,只需要替换原来注释掉的总标签层,同时微调y轴上限即可,核心修改片段:
# 把原代码的scale_y_continuous替换成下面这行,预留标签空间 scale_y_continuous(limits = c(0, 0.65)) + # 替换原来注释掉的geom_text层,添加柱端总标签 geom_text( data = df_t, aes(x = company, y = value, label = Label), inherit.aes = FALSE, # 关键:取消主图层的fill等映射继承,避免分组错位 hjust = -0.2, # 横向图下用hjust控制水平偏移,-0.2表示在柱末端右侧留少量间距 size = 3 )
完整可运行代码
library(tidyverse) # 构造基础数据 company=c('CompanyA','CompanyA', 'CompanyA', 'CompanyA','CompanyB', 'CompanyB', 'CompanyB', 'CompanyB') SubSegment = c('SubSeg1', 'SubSeg1', 'SubSeg2', 'SubSeg2', 'SubSeg1', 'SubSeg1', 'SubSeg2', 'SubSeg2') variable = c('Ratio1', 'Ratio2','Ratio1', 'Ratio2','Ratio1', 'Ratio2','Ratio1', 'Ratio2') value = c(0.311, 0.256, 0.389, 0.105, 0.256, 0.1002, 0.2569, 0.2856) df = as.data.frame(cbind(company, SubSegment, variable, value)) df=df%>% mutate(Label=value) df[,4:ncol(df)]<- sapply(df[,4:ncol(df)] , as.numeric) df[,ncol(df)]<- sapply(df[,ncol(df)] , function(x) scales::percent(x, accuracy = 0.1)) # 计算每个堆叠柱的总计值 df_t = df[,c(1,2,4)] df_t[,ncol(df_t)]<- sapply(df_t[,ncol(df_t)] , as.numeric) df_t = df_t %>% group_by(company, SubSegment) %>% summarise(value = sum(value), .groups = "drop") %>% mutate(Label=value) df_t[,ncol(df_t)]<- sapply(df_t[,ncol(df_t)] , function(x) scales::percent(x, accuracy = 0.1)) var_levels= c('Ratio1', 'Ratio2') colors= c("#F3DF6C", "cyan") plot.1<- ggplot(df, aes(fill=factor(variable, levels = var_levels), y=value, x=company)) + geom_bar(position="stack", stat="identity", alpha=1) + scale_y_continuous(limits = c(0, 0.65)) + # 柱内分段标签 geom_text(aes(label=Label), position = position_stack(vjust = 0.5), size=2.5) + # 柱端总计标签 geom_text( data = df_t, aes(x = company, y = value, label = Label), inherit.aes = FALSE, hjust = -0.2, size = 3 ) + facet_wrap(~factor(SubSegment ), ncol=1) + theme(plot.title = element_text(size = 11), axis.title.x = element_blank(), axis.title.y = element_blank(), axis.text.x = element_blank(), axis.ticks.x = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), legend.position = c(0.88, 0.89) , legend.text = element_text(size = 9.5), legend.title = element_text(size = 11), legend.background = element_rect(fill="gray92", linetype="solid",colour ="gray75")) + scale_fill_manual(values=colors, name="SubSegment") + coord_flip() plot(plot.1)
运行后即可实现效果:每个堆叠柱内部居中显示分段百分比标签,柱的最右端显示整柱总计百分比,标签不会被截断、也不会和柱体重叠。
内容的提问来源于stack exchange,提问作者lu-202
相关产品推荐
相关产品推荐

