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

如何解决R(ggplot)堆叠条形图标签拥挤与显示异常问题

解决堆叠条形图百分比标签重叠/溢出问题

我一直在解决堆叠条形图中占比过低的百分比标签溢出、显示异常的问题,始终找不到可行方案。从图的右侧能看到,选项C和D的标签经常挤在一起,完全读不出geom_text里的百分比。

我的数据框bloco包含以下字段:

  • Item:问卷题目(单个问题)
  • Alternative:对应题目的选项
  • p:该题目下对应选项的回答占比
  • Block:题目所属模块

原ggplot代码如下:

bloco %>%
  ggplot(aes(y = as.factor(Item), x = p, fill = Alternative, group = Block)) +
  geom_text(
    aes(y = as.factor(Item), x = p, label = p),
    # position = position_dodge(width = 1),
    size = 2.5
  ) +
  geom_bar(stat = "identity") +
  geom_text(
    aes(label = p),
    position = position_stack(vjust = 0.5),
    size = 3,
    color = "#413F1A"
    # nudge_x = -1,
    # hjust= 1
  ) +
  scale_fill_manual(
    name = ''
    , values = c(
      '(A) Nunca ou quase nunca.' = '#F9E79F',
      '(B) De vez em quando.' = '#F7DC6F',
      '(C) Quase sempre.' = '#F4D03F',
      "(D) Sempre." = "#F1C40F"
    )
  ) +
  scale_y_discrete(labels = label_wrap_gen(25))+
  scale_x_continuous(labels = scales::percent_format(scale = 100), limits = c(0, 1.02)
                     )+
  labs(#title = paste0("Gráfico ", ngraf,  ": Percepção dos professores sobre a segurança no contexto escolar."), 
    x = "Frequência de Respostas (%)", y = "") +
  theme_test() +
  theme(plot.title = element_text(size = 11)
        , legend.key.size = unit(0.3, 'cm')
        , legend.position = 'bottom')

我已经试过调整vjust参数和手动定位标签,都没用。


解决方案

1. 移除冗余的geom_text层

原代码中存在两个geom_text,第一个未使用position_stack,会直接在x=p的位置绘制标签,导致与堆叠后的标签重叠。先删除这层冗余代码。

2. 过滤低占比标签

设置阈值(比如5%,即p < 0.05),对低于阈值的标签不显示,避免内部拥挤:

# 修改geom_text部分
geom_text(
  aes(label = ifelse(p >= 0.05, scales::percent(p, accuracy = 1), "")),
  position = position_stack(vjust = 0.5),
  size = 3,
  color = "#413F1A"
)

这里用scales::percent将数值转为百分比格式,同时过滤小占比标签。

3. 扩大x轴范围

原x轴上限为1.02,接近1的堆叠条容易导致外部标签溢出,将上限调整为1.1:

scale_x_continuous(labels = scales::percent_format(scale = 100), limits = c(0, 1.1))

4. 把小占比标签移到条形外侧

若必须显示低占比标签,可通过条件判断调整hjust,将小占比标签放在条形右侧:

geom_text(
  aes(
    label = scales::percent(p, accuracy = 1),
    hjust = ifelse(p < 0.05, -0.1, 0.5)
  ),
  position = position_stack(vjust = 0.5),
  size = 3,
  color = "#413F1A"
)

5. 动态调整标签大小

根据占比设置不同字号,小占比标签用更小的字号减少重叠:

geom_text(
  aes(
    label = scales::percent(p, accuracy = 1),
    size = ifelse(p >= 0.05, 3, 2)
  ),
  position = position_stack(vjust = 0.5),
  color = "#413F1A",
  show.legend = FALSE # 避免生成大小图例
)

整合后的完整代码示例

bloco %>%
  ggplot(aes(y = as.factor(Item), x = p, fill = Alternative, group = Block)) +
  geom_bar(stat = "identity") +
  geom_text(
    aes(
      label = ifelse(p >= 0.05, scales::percent(p, accuracy = 1), ""),
      hjust = ifelse(p < 0.05, -0.1, 0.5)
    ),
    position = position_stack(vjust = 0.5),
    size = 3,
    color = "#413F1A"
  ) +
  scale_fill_manual(
    name = ''
    , values = c(
      '(A) Nunca ou quase nunca.' = '#F9E79F',
      '(B) De vez em quando.' = '#F7DC6F',
      '(C) Quase sempre.' = '#F4D03F',
      "(D) Sempre." = "#F1C40F"
    )
  ) +
  scale_y_discrete(labels = label_wrap_gen(25))+
  scale_x_continuous(labels = scales::percent_format(scale = 100), limits = c(0, 1.1))+
  labs(x = "Frequência de Respostas (%)", y = "") +
  theme_test() +
  theme(plot.title = element_text(size = 11)
        , legend.key.size = unit(0.3, 'cm')
        , legend.position = 'bottom')

内容的提问来源于stack exchange,提问作者João Augusto Freire

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 19:03:35