使用grid.arrange调整多图标题与图例的技术问题
问题描述
- 使用
grid.arrange排列6幅共享图例的ggplot绘图时,添加公共图例会导致绘图尺寸被压缩 - 需要给每列左上角添加标题,但目前仅在第一列中间位置添加了单个标题
可复现代码
library(ggplot2) library(grid) library(gridExtra) set.seed(123) a_SYS <- data.frame( Sampling_NR = rep(1:10, 2), ACM = c(runif(10, 100, 130), runif(10, 110, 140)), ACS = c(runif(10, 1, 5), runif(10, 1, 6)), Stress = rep(c("one", "two"), each = 10) ) # 基础绘图模板 plot_A <- ggplot(data = a_SYS, aes(x = Sampling_NR, y = ACM, group = Stress, colour = Stress, shape = Stress)) + geom_line() + geom_errorbar(aes(ymin=ACM-ACS, ymax=ACM+ACS), width= .2) + geom_point() + geom_vline(xintercept = c(a_SYS$Sampling_NR[4], a_SYS$Sampling_NR[5]), linetype = "dashed", color = "gray80") + ggtitle("") + theme_minimal() + scale_y_continuous(breaks = seq(90,140,20), limits = c(90, 140), name = "") + labs(x = "Time in min", y = "") + scale_color_manual(values = c("gray50", "black"), labels = c("C-TSST", "TSST"), name = "SYS") + scale_x_discrete(labels = c("-80", "-60", "-40", "-20", "0", "+20", "+40", "+60", "+80", "+100")) + theme(legend.position = "none", legend.box = "horizontal", axis.title.x = element_text(size = 9.5), axis.title.y = element_text(size = 9.5), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), axis.line = element_line(color = "black"), axis.ticks = element_line(color = "black")) # 原布局代码(仅作参考) tg1 <- textGrob('A', gp = gpar(fontsize = 17, fontface = 'bold')) # BM3 <- grid.arrange(tg1,NULL,plot_A,plot_A,plot_A,plot_A,plot_A,plot_A,ncol = 2, nrow = 5)
当前效果

修正方案
1. 单独提取并放置公共图例
先从绘图中提取独立的图例对象,再将图例与绘图分开布局,避免挤占绘图空间:
# 提取公共图例(设置为横向底部布局) legend_obj <- get_legend( plot_A + theme(legend.position = "bottom", legend.box = "horizontal", legend.title = element_text(size = 10), legend.text = element_text(size = 9)) )
2. 添加列标题并调整整体布局
创建两列的标题文本框,然后按「标题行 + 三行绘图 + 图例行」的结构排列,通过heights参数控制各区域高度,确保绘图尺寸不受压缩:
# 创建列标题 col_title1 <- textGrob('A', gp = gpar(fontsize = 17, fontface = 'bold')) col_title2 <- textGrob('B', gp = gpar(fontsize = 17, fontface = 'bold')) # 整体布局:2列,5行(标题行1行 + 绘图3行 + 图例1行) final_plot <- grid.arrange( col_title1, col_title2, # 第一行:列标题 plot_A, plot_A, # 第二行:绘图1-2 plot_A, plot_A, # 第三行:绘图3-4 plot_A, plot_A, # 第四行:绘图5-6 legend_obj, legend_obj, # 第五行:图例(跨两列,实际只显示一个) ncol = 2, heights = c(0.5, 2, 2, 2, 0.8), # 分配各行高度,绘图行占比最大 widths = c(1, 1), # 两列宽度一致 layout_matrix = rbind( c(1,2), c(3,4), c(5,6), c(7,8), c(9,9) # 图例跨两列显示 ) )
关键说明
get_legend()单独提取图例,避免图例嵌入每个绘图导致重复或尺寸压缩layout_matrix指定图例跨两列显示,保证图例居中heights参数优先分配空间给绘图行,确保绘图尺寸足够- 列标题放在第一行对应列的位置,实现左上角标题效果
内容的提问来源于stack exchange,提问作者Masal Gezici
相关产品推荐
相关产品推荐

