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

如何在R的ggplot2中自动调整条形图内文本大小并避免重叠

堆叠条形图文本重叠问题解决方法

问题背景

现有一个名为df的数据框,结构如下:

df
# A tibble: 15 × 3
# Groups:   var1 [3]
   var1   var2                       per
   <chr>  <fct>                    <dbl>
 1 My own "Very \n Dissatisfied" 0.00751
 2 My own "Dissatisfied"         0.0641 
 3 My own "Neutral"              0.353  
 4 My own "Satisfied"            0.384  
 5 My own "Very \n Satisfied"    0.192  
 6 No     "Very \n Dissatisfied" 0.0445 
 7 No     "Dissatisfied"         0.135  
 8 No     "Neutral"              0.417  
 9 No     "Satisfied"            0.273  
10 No     "Very \n Satisfied"    0.130  
11 Yes    "Very \n Dissatisfied" 0.0233 
12 Yes    "Dissatisfied"         0.0639 
13 Yes    "Neutral"              0.280  
14 Yes    "Satisfied"            0.340  
15 Yes    "Very \n Satisfied"    0.293  

使用以下ggplot2代码绘制堆叠条形图时,出现了文本重叠的问题:

ggplot(df,aes(x=var1,y=per,fill=var2))+
  geom_col(position = position_fill(reverse = TRUE))+
  theme(axis.title.y=element_blank(),axis.title.x=element_blank())+
  coord_flip()+
  scale_fill_brewer(palette ="RdYlGn",direction = 1,type="div")+
  theme(axis.text.y=element_text(size=12, angle=0,hjust=0,vjust=0))+
  theme(axis.text.x=element_text(size=12, angle=0,hjust=0,vjust=0)) +
  theme(legend.text=element_text(size = 15), 
        legend.title = element_blank()  )+
  scale_y_continuous(labels = scales::percent)+
  geom_text(aes(label = scales::percent(round(per,2))), position = position_stack(reverse = TRUE, vjust = .5))

问题原因

  1. 位置逻辑不匹配:geom_col用position_fill()将条形转为比例占比,但geom_text用position_stack()基于原始数值计算位置,导致文本位置偏移。
  2. 极小占比分组干扰:部分分组(如"Very \n Dissatisfied")占比过低,文本空间不足导致重叠。

解决方法

修改后的完整代码

library(ggplot2)
library(scales)
library(dplyr)

# 预处理:过滤占比过低的分组,避免文本拥挤
df_filtered <- df %>% 
  mutate(label = ifelse(per >= 0.03, percent(per, accuracy = 1), ""))

ggplot(df_filtered, aes(x = var1, y = per, fill = var2)) +
  geom_col(position = position_fill(reverse = TRUE)) +
  # 统一用position_fill匹配条形位置,确保文本落在分组中心
  geom_text(aes(label = label), 
            position = position_fill(reverse = TRUE, vjust = 0.5),
            size = 4) +
  coord_flip() +
  scale_fill_brewer(palette = "RdYlGn", direction = 1, type = "div") +
  scale_y_continuous(labels = percent) +
  theme(
    axis.title = element_blank(),
    axis.text.y = element_text(size = 12, hjust = 0),
    axis.text.x = element_text(size = 12),
    legend.text = element_text(size = 15),
    legend.title = element_blank()
  )

关键修改点

  • 统一位置参数:将geom_text的position改为position_fill(reverse = TRUE, vjust = 0.5),与geom_col的位置逻辑保持一致,确保文本精准落在对应分组中心。
  • 过滤极小占比文本:添加预处理步骤,仅保留占比≥3%的分组文本,避免小分组的文本拥挤重叠。
  • 优化文本格式:用percent(per, accuracy = 1)直接生成百分比文本,保留一位小数,避免提前round导致的精度丢失。
  • 简化theme设置:合并重复的theme调用,让代码更简洁易读。

数据结构代码(可直接复制使用)

structure(list(var1 = c("My own", "My own", "My own", "My own", 
"My own", "No", "No", "No", "No", "No", "Yes", "Yes", "Yes", 
"Yes", "Yes"), var2 = structure(c(1L, 2L, 3L, 4L, 5L, 1L, 2L, 
3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L), levels = c("Very \n Dissatisfied", 
"Dissatisfied", "Neutral", "Satisfied", "Very \n Satisfied"), class = "factor"), 
    per = c(0.00751285092922104, 0.0640569395017794, 0.352708580466588, 
    0.383550810597074, 0.192170818505338, 0.0445205479452055, 
    0.134703196347032, 0.417237442922374, 0.273401826484018, 
    0.13013698630137, 0.0233160621761658, 0.0639032815198618, 
    0.27979274611399, 0.340241796200345, 0.292746113989637)), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -15L), groups = structure(list(
    var1 = c("My own", "No", "Yes"), .rows = structure(list(1:5, 
        6:10, 11:15), ptype = integer(0), class = c("vctrs_list_of", 
    "vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -3L), .drop = TRUE))

内容的提问来源于stack exchange,提问作者Homer Jay Simpson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 04:47:34