为分面比例柱状图添加柱顶标签
给分面比例柱状图添加顶部比例标签
你可以先在数据层面提前计算好各区域不同响应类型的比例,这样后续用geom_text时映射参数会更清晰,避免依赖ggplot的内部统计变量。具体代码如下:
library(tidyverse) # 原始数据 data <- data.frame(district = c("South", "North", "North", "West", "South", "South", "West"), response = c(2,3,5,4,4,3,3)) # 预处理数据:计算每个区域内各响应类型的比例 data_summary <- data %>% mutate(response = case_when(response < 3.5 ~ "no/neutral", response > 3.5 ~ "yes")) %>% count(district, response) %>% group_by(district) %>% mutate(proportion = n / sum(n), # 格式化比例为带%的文本,保留两位小数 proportion_label = sprintf("%.2f%%", proportion * 100)) # 绘图 ggplot(data_summary, aes(x = response, y = proportion, fill = response)) + scale_fill_manual(values = c("#E69F00", "#009E73")) + theme(legend.position = "none") + geom_bar(stat = "identity") + # 因为已提前计算好比例,用identity统计 # 添加顶部标签,y轴稍作上调避免和柱子顶部重叠 geom_text(aes(label = proportion_label), vjust = -0.5, size = 4) + facet_wrap(vars(district)) + labs(x = "Response", y = "Proportion") + scale_y_continuous(labels = scales::percent_format()) # 可选:把y轴刻度转为百分比格式
关键说明:
- 先用
count()统计每个区域-响应组合的数量,再通过group_by(district)计算该区域内的比例,数据逻辑更透明,也方便后续标签映射。 geom_text的y直接映射到提前计算好的proportion,vjust = -0.5让标签在柱子上方显示,避免重叠。sprintf("%.2f%%", proportion * 100)把比例转换成带百分号的文本,你可以根据需求调整小数位数(比如改成%.1f%%保留一位小数)。
如果坚持想用原代码的方式(不提前汇总数据),也可以用stat_count配合after_stat来获取比例,代码如下:
data %>% mutate(response = case_when(response < 3.5 ~ "no/neutral", response > 3.5 ~ "yes")) %>% ggplot(aes(x = response, fill = response)) + scale_fill_manual(values = c("#E69F00", "#009E73")) + theme(legend.position="none") + geom_bar(aes(y = after_stat(count / tapply(count, PANEL, sum)[PANEL]))) + # 添加标签,用after_stat获取计算后的比例 geom_text(stat = "count", aes(y = after_stat(count / tapply(count, PANEL, sum)[PANEL]), label = sprintf("%.2f%%", after_stat(count / tapply(count, PANEL, sum)[PANEL]) * 100)), vjust = -0.5, size = 4) + facet_wrap(vars(district)) + labs(x = "Response", y = "Proportion") + scale_y_continuous(labels = scales::percent_format())
不过第一种提前汇总数据的方式更易读和维护,推荐使用。
内容的提问来源于stack exchange,提问作者Maggie
相关产品推荐
相关产品推荐

