You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为分面比例柱状图添加柱顶标签

给分面比例柱状图添加顶部比例标签

你可以先在数据层面提前计算好各区域不同响应类型的比例,这样后续用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 22:57:20