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

ggplot2绘制李克特量表堆叠图:geom_label_repel标签位置异常问题

解决ggplot2堆叠柱状图小占比标签排斥问题的方案

核心思路

通过拆分数据+预计算标签位置,分别处理大占比和小占比标签:大占比标签用geom_label原位显示,小占比标签用geom_label_repel仅在Y轴方向排斥,同时保证X轴位置准确。

完整代码示例

library(tidyverse)
library(ggrepel)

# 模拟李克特量表数据(替换成你的真实数据)
set.seed(123)
df <- tibble(
  question = rep(paste0("Q", 1:3), each = 5),
  response = factor(rep(1:5, 3), labels = c("非常不同意", "不同意", "中立", "同意", "非常同意")),
  count = c(10, 25, 40, 15, 10, 5, 10, 60, 20, 5, 2, 8, 70, 15, 5)
) %>%
  group_by(question) %>%
  mutate(
    percentage = count / sum(count) * 100,
    # 预计算堆叠柱状图中每个标签的Y轴中点位置(避免自动计算错位)
    y_pos = cumsum(percentage) - percentage / 2
  ) %>%
  ungroup()

# 设定占比阈值(可根据需求调整,比如5%)
threshold <- 5
df_large <- df %>% filter(percentage >= threshold)  # 大占比数据
df_small <- df %>% filter(percentage < threshold)   # 小占比数据

# 绘图
ggplot(df, aes(x = question, y = percentage, fill = response)) +
  geom_col(position = position_stack()) +
  # 大占比标签:原位显示
  geom_label(data = df_large, aes(y = y_pos, label = sprintf("%.1f%%", percentage)),
             position = position_stack(vjust = 0.5), size = 3, fill = "white") +
  # 小占比标签:仅Y轴方向排斥,X轴固定
  geom_label_repel(data = df_small, aes(y = y_pos, label = sprintf("%.1f%%", percentage)),
                   size = 3, fill = "white",
                   direction = "y",  # 限制仅Y轴调整位置
                   nudge_x = 0,      # X轴位置固定
                   xlim = c(0.5, length(unique(df$question)) + 0.5),  # 防止标签超出X轴范围
                   force = 1) +      # 调整排斥力度(数值越大排斥越强)
  labs(x = "问题", y = "百分比", fill = "反馈") +
  theme_minimal()

关键细节说明

  1. 预计算Y轴位置:通过y_pos = cumsum(percentage) - percentage / 2手动计算每个标签的堆叠中点,避免ggplot自动计算时出现的X轴错位问题。
  2. 拆分数据处理:按阈值将数据分成两组,分别对应不同的标签函数,避免所有标签被不必要排斥。
  3. 限制排斥方向:direction = "y"强制geom_label_repel仅在Y轴方向调整标签位置,确保X轴与对应柱状图对齐。
  4. 边界控制:xlim参数防止小占比标签被推出绘图区域外,保证可视化完整性。

内容的提问来源于stack exchange,提问作者Morrigan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 04:01:06