R语言堆叠条形图添加文本的三类问题及代码求助
R语言堆叠条形图百分比标注优化方案
问题说明
尝试为ggplot2中的横向堆叠条形图添加百分比文本标注时,遇到以下三个问题:
- 标注文本未正确居中对齐
- 部分类别(如WC)各占比相等时需按图例顺序排列,其余场景需按
Contribution值降序排序堆叠 - 0%占比的标注需要隐藏
原始数据与代码
数据
df <- structure(list(QT = c("BMI", "BMI", "BMI", "BMI", "BMI", "WHR", "WHR", "WHR", "WHR", "WHR", "BF", "BF", "BF", "BF", "BF", "WC", "WC", "WC", "WC", "WC"), E = c("HD", "NS", "PA", "PALC", "SMK", "HD", "NS", "PA", "PALC", "SMK", "HD", "NS", "PA", "PALC", "SMK", "HD", "NS", "PA", "PALC", "SMK"), Contribution = c(21.73913043, 0, 21.73913043, 34.7826087, 21.73913043, 24.13793103, 24.13793103, 20.68965517, 13.79310345, 17.24137931, 16.66666667, 16.66666667, 20, 20, 26.66666667, 20, 20, 20, 20, 20)), row.names = c(NA, 20L), class = "data.frame")
原始代码
library(ggplot2) ggplot(df, aes(x = Contribution, y = QT, fill = E)) + geom_col(size=0.5, color="black", position = position_fill(reverse = TRUE)) + scale_fill_brewer(palette = "Set2") + theme_minimal()+ theme(axis.text=element_text(size=12, colour = "black"), axis.title = element_text(size=13), axis.text.x = element_blank(), legend.text = element_text(size=12))+ geom_text(aes(label = paste0(round(Contribution), "%")), position = position_fill(vjust = 0.5))
当前效果

解决方案
步骤1:数据预处理(实现分组排序)
使用dplyr对数据分组处理,针对不同组设置排序规则:
library(dplyr) df_sorted <- df %>% group_by(QT) %>% mutate( # 判断组内所有占比是否相等 all_equal = n_distinct(Contribution) == 1, # 定义排序依据:相等则按图例顺序,否则按占比降序 sort_key = if(all_equal) as.integer(factor(E, levels = c("HD", "NS", "PA", "PALC", "SMK"))) else desc(Contribution) ) %>% ungroup() %>% # 按分组和排序键重新排序 arrange(QT, sort_key) %>% # 将E转换为排序后的因子,确保堆叠顺序正确 mutate(E = factor(E, levels = unique(E)))
步骤2:优化绘图代码(解决居中和隐藏0%标注)
调整geom_text参数,与geom_col保持一致的堆叠设置,并隐藏0%标注:
library(ggplot2) ggplot(df_sorted, aes(x = Contribution, y = QT, fill = E)) + geom_col(size = 0.5, color = "black", position = position_fill(reverse = TRUE)) + scale_fill_brewer(palette = "Set2") + theme_minimal() + theme( axis.text = element_text(size = 12, colour = "black"), axis.title = element_text(size = 13), axis.text.x = element_blank(), legend.text = element_text(size = 12) ) + geom_text( # 隐藏0%标注,仅显示非零占比的百分比文本 aes(label = ifelse(Contribution == 0, "", paste0(round(Contribution), "%"))), # 与geom_col使用完全一致的堆叠参数,保证文本居中 position = position_fill(reverse = TRUE, vjust = 0.5), size = 4 # 可根据需求调整文本大小 )
方案说明
- 标注居中:
geom_text的position_fill参数与geom_col完全匹配(包含reverse = TRUE),确保文本位置与堆叠块对齐。 - 分组排序:通过预处理数据,给每个分组设置差异化排序规则,占比相等的组按图例顺序排列,其他组按占比降序堆叠。
- 隐藏0%标注:使用
ifelse判断占比,为0时返回空字符串,不显示标注。
内容的提问来源于stack exchange,提问作者Dovini Jayasinghe
相关产品推荐
相关产品推荐

