R语言ggplot堆叠条形图标签居中及双Y轴添加问题
问题与解决方案
一、堆叠柱状图数据标签不居中的问题
问题原因
你的geom_bar使用了position_stack(reverse = TRUE)反转了堆叠顺序,但geom_text的position_stack未同步设置reverse = TRUE,导致标签的堆叠方向与柱子的堆叠方向不一致,最终标签无法居中对应区块。
解决方法
方法1:同步堆叠反转设置
修改geom_text的position参数,添加reverse = TRUE,让标签堆叠方向与柱子保持一致:
ggplot(test, aes(x=name, y=value, fill=type)) + geom_bar(position = position_stack(reverse = TRUE), stat='identity') + theme(plot.title = element_text(hjust = 0.5)) + scale_fill_manual(values = c("#0099f9", "#69c6ff")) + # 同步设置reverse=TRUE geom_text(aes(label = value), position = position_stack(reverse = TRUE, vjust = 0.5), colour = "black", size = 3) + guides(fill = guide_legend(title = "", reverse = TRUE))
方法2:手动计算标签位置(更可控)
预处理数据,计算每个堆叠区块的中点位置,直接指定标签的y坐标:
library(dplyr) # 按堆叠顺序计算每个区块的中点 test_processed <- test %>% arrange(name, desc(type)) %>% group_by(name) %>% mutate(cum_value = cumsum(value), mid_value = cum_value - value/2) # 绘图 ggplot(test_processed, aes(x=name, y=value, fill=type)) + geom_bar(position = position_stack(reverse = TRUE), stat='identity') + theme(plot.title = element_text(hjust = 0.5)) + scale_fill_manual(values = c("#0099f9", "#69c6ff")) + geom_text(aes(y=mid_value, label=value), colour="black", size=3) + guides(fill = guide_legend(title = "", reverse = TRUE))
二、添加百分比双Y轴的实现
通过sec_axis实现双轴,需先建立百分比与原数值轴的映射关系:
步骤1:预处理数据
# 将百分比转为数值格式 test2 <- test2 %>% mutate(share_num = as.numeric(sub("%", "", share))/100) # 计算原数据的最大值,用于建立轴的映射关系 max_total <- test %>% group_by(name) %>% summarise(total = sum(value)) %>% pull(total) %>% max()
步骤2:绘制双轴图表
ggplot() + # 原堆叠柱状图 geom_bar(data=test, aes(x=name, y=value, fill=type), position=position_stack(reverse=TRUE), stat='identity') + # 添加百分比标签(位置可根据需求调整) geom_text(data=test2, aes(x=name, y=max_total*share_num, label=share), colour="darkred", size=3, hjust=-0.1) + # 设置主、次Y轴 scale_y_continuous( name = "数值", sec.axis = sec_axis( ~./max_total, name = "占比 (%)", labels = function(x) paste0(round(x*100), "%") ) ) + scale_fill_manual(values = c("#0099f9", "#69c6ff")) + theme( plot.title = element_text(hjust=0.5), axis.title.y.right = element_text(colour="darkred"), axis.text.y.right = element_text(colour="darkred") ) + guides(fill = guide_legend(title = "", reverse = TRUE))
说明
- 次轴是视觉映射的虚拟轴,需确保百分比与原数值的转换关系正确;
- 可通过调整
geom_text的hjust、y参数修改百分比标签的显示位置。
内容的提问来源于stack exchange,提问作者Who
相关产品推荐
相关产品推荐

