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:增大网格宽度,避免内容截断
- 调整保存尺寸:在
ggsave中指定足够大的宽度,给每个facet留出充足空间,示例:
ggsave('plots/my_plot.png', myPlot, bg='transparent', dpi = 300, width = 18, height = 8)
可根据实际效果调整width数值,数值越大,网格横向空间越充足。
- 增大面板间距:在
theme中添加panel.spacing参数,避免facet之间挤压:
theme( # ... 保留原有theme设置 panel.spacing = unit(1, "cm") # 控制面板间的横向间距 )
- 缩小条形宽度:适当减小
geom_bar和geom_bar_pattern的width参数,给标签留出更多空间:
geom_bar(stat = "identity", width = 0.7) geom_bar_pattern(stat = "identity", width = 0.7, # 同步调整pattern条形宽度 # ... 保留其他参数 )
针对需求B:解决标签重叠问题
- 手动调整标签位置:根据
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)
- 使用自动避重工具:安装
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)
- 缩小标签字体:若位置调整后仍有重叠,可适当减小标签的
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
相关产品推荐
相关产品推荐

