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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 11:45:03