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

ggplot2中无法调整网格边距,如何增大网格宽度并解决标签重叠?

问题描述

我尝试过调整边距的方案,但没有效果。当前网格尺寸过小,核心需求是增大网格宽度,完整显示所有条形图及其对应的n/比例(蓝色标注部分),同时解决标签重叠问题(红色标注部分)。

核心需求

  • A) 增大网格宽度,避免截断n值和比例值(蓝色部分)
  • B) 解决标签重叠问题(红色部分)

原代码
### packages:
library(tidyverse)
library(stringr)
library(RColorBrewer)
library(viridis)
library(tidyquant) # theme function:
library(cowplot) # Join plots
library(ggpattern)
library(ggtext) ## use markdown inside ggplot2

### plot:
  
### set fonts:
library(showtext)
  
sysfonts::font_add_google("Montserrat", family = "Mont")
t3 <- "Mont"

## Allows the use of the downloaded Google Font (from Ícaro)
## To see the results updated, it's needed to call windows() or save the image
showtext::showtext_opts(dpi = 300)
showtext::showtext_auto()

### set colors:
g1 <- c('yellow', 'darkgrey')
names(g1) <- c('Separated', 'Together')

### plot it:
myPlot <- myData %>% 
  ggplot(aes(y = prop, x = as.ordered(Q40), fill = as.ordered(Q40), pattern = Q9)) + 
  geom_bar(stat = "identity", width = 0.9) + 
  scale_fill_manual(values = g1, name = NULL) +
  ### dont change:
  geom_bar_pattern(stat = "identity",
                   width = 0.9,
                   color = "black",
                   pattern_fill = "black",
                   pattern_angle = 45,
                   pattern_density = 0.35, # 0.35
                   pattern_spacing = 0.1, # 0.025
                   pattern_alpha = 0.3,
                   show.legend = FALSE, # omit pattern from legend
                   pattern_shape = 'convex3') +  #triangule
  scale_pattern_manual(values = c('Bilíngue' = 'crosshatch'), guide = 'none') +
  geom_text(aes(label = str_glue('{round(prop, 1.5)} %')),
            nudge_y = 5,
            vjust = 0.4,
            size = 5) + 
  geom_label(aes(label= str_glue('n = {n}')),
             size = 5,
             nudge_x = 0.3,
             show.legend = FALSE) +
  
  scale_y_continuous(labels=scales::percent_format(scale = 1)) +
  
  labs(x = "Tipe of Q40", y = 'Proportion (%)') +
  facet_grid(~ LEVEL, scales="free_x") +
  theme_tq() +
  theme( 
    text = element_text(family = t3, size = 4.5),
    panel.background = element_rect(fill='transparent'), #transparent panel bg
    plot.background = element_rect(fill='transparent', color=NA), #transparent plot bg
    panel.grid.major = element_blank(), #remove major gridlines
    panel.grid.minor = element_blank(), #remove minor gridlines
    legend.background = element_rect(fill='transparent'), #transparent legend bg
    legend.box.background = element_rect(fill='transparent'), #transparent legend panel
    legend.box.margin = margin(t = 2, r = 1, b = 2, l = 1),
    plot.margin = margin(t = 0, r = 15, b = 0, l = 15),
    legend.position = "bottom",
    legend.box.spacing = unit('0.5', "cm"),
    legend.title=element_text(size = 25),
    legend.text=element_text(size=20), 
    axis.title.x = element_text(vjust = -1.5, size=20), # change 'X legend label'
    axis.text.x = element_text(size = 8.5,  # legend of ticks points 
                               angle = 0,
                               hjust = 0.5, 
                               face = "bold"),
    axis.title.y = element_text(size=20, margin = margin(t = 0, r = 10, b = 0, l = 10)), # change 'proporção'
    axis.text.y = element_text(size = 15, face = "bold", hjust = 1),
    ### grid: ## HELPPP!!!
    strip.text.x = element_text(face = "bold", family = t3, size = 13, colour = 'yellow'),
    strip.background = element_rect(size = 25, fill = '#3A4388'),
    # panel.margin = unit(-5, "lines"), # new : panel.spacing ## not working
    #  strip.switch.pad.grid = unit(20, "cm") # not working
  )

ggsave('plots/', myPlot, bg='transparent', dpi = 300)

原数据
structure(list(Q40 = structure(c(1L, 2L, 1L, 2L, 1L, 2L, 1L, 
2L, 1L, 2L), .Label = c("Separated", "Together"), class = "factor"), 
    Q9 = structure(c(3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("Extracurricular", 
    "CH Estendida", "Bilíngue", "Internacional"), class = "factor"), 
    n = c(6L, 17L, 7L, 11L, 7L, 11L, 6L, 6L, 2L, 2L), prop = c(26.09, 
    73.91, 38.89, 61.11, 38.89, 61.11, 50, 50, 50, 50), sd = c(0.34, 
    0.34, 0.16, 0.16, 0.16, 0.16, 0, 0, 0, 0), LEVEL = structure(c(1L, 
    1L, 2L, 2L, 3L, 3L, 4L, 4L, 5L, 5L), .Label = c("Level One", 
    "Level Two", "Level Threee", "Level Four", "Level Five"), class = "factor")), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -10L), groups = structure(list(
    Q9 = structure(3L, .Label = c("Extracurricular", "CH Estendida", 
    "Bilíngue", "Internacional"), class = "factor"), .rows = structure(list(
        1:10), ptype = integer(0), class = c("vctrs_list_of", 
    "vctrs_vctr", "list"))), row.names = c(NA, -1L), class = c("tbl_df", 
"tbl", "data.frame"), .drop = TRUE))

解决方案

针对需求A:增大网格宽度,避免内容截断

  1. 调整保存尺寸:在ggsave中指定足够大的宽度,给每个facet留出充足空间,示例:
ggsave('plots/my_plot.png', myPlot, bg='transparent', dpi = 300, width = 18, height = 8)

可根据实际效果调整width数值,数值越大,网格横向空间越充足。

  1. 增大面板间距:在theme中添加panel.spacing参数,避免facet之间挤压:
theme(
  # ... 保留原有theme设置
  panel.spacing = unit(1, "cm") # 控制面板间的横向间距
)
  1. 缩小条形宽度:适当减小geom_bar和geom_bar_pattern的width参数,给标签留出更多空间:
geom_bar(stat = "identity", width = 0.7)
geom_bar_pattern(stat = "identity", width = 0.7, # 同步调整pattern条形宽度
                 # ... 保留其他参数
                 )

针对需求B:解决标签重叠问题

  1. 手动调整标签位置:根据Q40类别设置不同的偏移量,分开比例标签和n标签:
geom_text(aes(label = str_glue('{round(prop, 1.5)} %'),
              nudge_x = ifelse(Q40 == "Separated", -0.15, 0.15)),
          nudge_y = 5,
          vjust = 0.4,
          size = 5) + 
geom_label(aes(label= str_glue('n = {n}'),
               nudge_x = ifelse(Q40 == "Separated", -0.3, 0.3)),
           size = 5,
           show.legend = FALSE)
  1. 使用自动避重工具:安装ggrepel包,用geom_text_repel和geom_label_repel替代原生标签函数,自动计算不重叠位置:
install.packages("ggrepel")
library(ggrepel)

# 替换原有标签代码
geom_text_repel(aes(label = str_glue('{round(prop, 1.5)} %')),
                nudge_y = 5,
                size = 5,
                show.legend = FALSE) +
geom_label_repel(aes(label= str_glue('n = {n}')),
                 size = 5,
                 show.legend = FALSE)
  1. 缩小标签字体:若位置调整后仍有重叠,可适当减小标签的size参数,比如从5调整到4.5。

整合后的完整代码
### packages:
library(tidyverse)
library(stringr)
library(RColorBrewer)
library(viridis)
library(tidyquant)
library(cowplot)
library(ggpattern)
library(ggtext)
library(showtext)
library(ggrepel) # 新增自动避重包

### set fonts:
sysfonts::font_add_google("Montserrat", family = "Mont")
t3 <- "Mont"

showtext::showtext_opts(dpi = 300)
showtext::showtext_auto()

### set colors:
g1 <- c('yellow', 'darkgrey')
names(g1) <- c('Separated', 'Together')

### plot it:
myPlot <- myData %>% 
  ggplot(aes(y = prop, x = as.ordered(Q40), fill = as.ordered(Q40), pattern = Q9)) + 
  geom_bar(stat = "identity", width = 0.7) + 
  scale_fill_manual(values = g1, name = NULL) +
  geom_bar_pattern(stat = "identity",
                   width = 0.7,
                   color = "black",
                   pattern_fill = "black",
                   pattern_angle = 45,
                   pattern_density = 0.35,
                   pattern_spacing = 0.1,
                   pattern_alpha = 0.3,
                   show.legend = FALSE,
                   pattern_shape = 'convex3') +
  scale_pattern_manual(values = c('Bilíngue' = 'crosshatch'), guide = 'none') +
  # 使用ggrepel自动避免标签重叠
  geom_text_repel(aes(label = str_glue('{round(prop, 1.5)} %')),
                  nudge_y = 5,
                  size = 4.5,
                  show.legend = FALSE) + 
  geom_label_repel(aes(label= str_glue('n = {n}')),
                   size = 4.5,
                   show.legend = FALSE) +
  scale_y_continuous(labels=scales::percent_format(scale = 1)) +
  labs(x = "Type of Q40", y = 'Proportion (%)') +
  facet_grid(~ LEVEL, scales="free_x") +
  theme_tq() +
  theme( 
    text = element_text(family = t3, size = 4.5),
    panel.background = element_rect(fill='transparent'),
    plot.background = element_rect(fill='transparent', color=NA),
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    legend.background = element_rect(fill='transparent'),
    legend.box.background = element_rect(fill='transparent'),
    legend.box.margin = margin(t = 2, r = 1, b = 2, l = 1),
    plot.margin = margin(t = 0, r = 15, b = 0, l = 15),
    legend.position = "bottom",
    legend.box.spacing = unit('0.5', "cm"),
    legend.title=element_text(size = 25),
    legend.text=element_text(size=20), 
    axis.title.x = element_text(vjust = -1.5, size=20),
    axis.text.x = element_text(size = 8.5, angle = 0, hjust = 0.5, face = "bold"),
    axis.title.y = element_text(size=20, margin = margin(t = 0, r = 10, b = 0, l = 10)),
    axis.text.y = element_text(size = 15, face = "bold", hjust = 1),
    strip.text.x = element_text(face = "bold", family = t3, size = 13, colour = 'yellow'),
    strip.background = element_rect(size = 25, fill = '#3A4388'),
    panel.spacing = unit(1, "cm") # 增大面板间距
  )

# 调整保存尺寸
ggsave('plots/my_plot.png', myPlot, bg='transparent', dpi = 300, width = 18, height = 8)

内容的提问来源于Stack Exchange,提问作者Larissa Cury

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 12:54:57