在R中如何从另一个DataFrame向堆叠柱状图添加顶部geom_text
解决ggplot2堆叠柱状图顶部添加跨数据集百分比文本的问题
核心思路
要在堆叠柱状图顶部显示来自另一数据集的百分比,关键是让文本数据集的行数与x轴分组数(月份)完全匹配,同时将文本的y值设为对应月份堆叠柱的总高度。
完整示例代码
先模拟测试数据,再给出绘图代码:
# 加载所需包 library(ggplot2) library(dplyr) # 模拟sum_slaughter_2021数据集(月份、类别、屠宰总量) sum_slaughter_2021 <- tibble( month = rep(1:12, each = 3), kind = rep(c("牛", "猪", "羊"), 12), total_slaughter = sample(100:500, 36, replace = TRUE) ) # 模拟month_rate_2021数据集(月份、月度比率) month_rate_2021 <- tibble( month = 1:12, month_rate = runif(12, 0.1, 0.5) ) # 1. 预处理文本数据:计算每个月份的堆叠柱总高度,并与月度比率合并 text_data <- sum_slaughter_2021 %>% group_by(month) %>% summarise(total_height = sum(total_slaughter), .groups = "drop") %>% left_join(month_rate_2021, by = "month") # 2. 绘制堆叠柱状图+顶部百分比文本 ggplot(sum_slaughter_2021, aes(x = month, y = total_slaughter, fill = kind)) + geom_col() + # 添加顶部文本:指定text_data为数据源,y值用总高度 geom_text(data = text_data, aes(x = month, y = total_height, label = scales::percent(month_rate)), vjust = -0.3, # 调整垂直位置,让文本在柱子上方 size = 3.5) + labs(x = "月份", y = "屠宰总量", fill = "类别") + theme_minimal()
关键细节说明
解决美学长度不匹配:
原错误是因为sum_slaughter_2021是每个月份对应多行(不同类别),而month_rate_2021是每个月份对应一行,直接引用会导致行数不匹配。通过按月份汇总总高度,再合并比率数据,得到每个月份一行的text_data,完美匹配x轴的12个分组。文本位置调整:
vjust = -0.3:将文本向上偏移,避免被堆叠柱挡住;数值可根据实际柱子高度微调。scales::percent():将小数格式的month_rate转换成百分比字符串(如0.25→25%),提升可读性。
数据匹配注意事项:
确保两个数据集的month列类型完全一致(比如都是数值型1-12,或都是字符型"1月""2月"),否则left_join会匹配失败。
简化写法(无需单独预处理)
也可以直接在geom_text的data参数中完成数据汇总与合并,代码更紧凑:
ggplot(sum_slaughter_2021, aes(x = month, y = total_slaughter, fill = kind)) + geom_col() + geom_text(data = ~ .x %>% group_by(month) %>% summarise(total_height = sum(total_slaughter), .groups = "drop") %>% left_join(month_rate_2021, by = "month"), aes(x = month, y = total_height, label = scales::percent(month_rate)), vjust = -0.3, size = 3.5) + labs(x = "月份", y = "屠宰总量", fill = "类别") + theme_minimal()
内容的提问来源于stack exchange,提问作者seungwoolee
相关产品推荐
相关产品推荐

