使用ggplot、cowplot和tidyterra绘制3×3栅格图的尺寸适配问题
解决ggplot+cowplot+tidyterra绘制带标题/轴标签的栅格布局尺寸适配问题
核心思路
要解决布局偏移、间距不均的问题,关键是强制所有子图的绘图区域尺寸完全一致,再通过统一边距、对齐参数组合元素,避免标题、轴标签挤占绘图空间导致的布局混乱。具体步骤如下:
步骤1:统一子图格式
为所有子图设置基础主题,按需控制元素显示:
- 首列图保留y轴标签、刻度,非首列隐藏
- 首行图保留标题,非首行隐藏
- 所有图设置统一边距,消除默认边距差异
步骤2:对齐绘图区域
用cowplot::align_plots()强制所有子图的绘图区域水平/垂直对齐,抵消轴标签、标题带来的尺寸偏差。
步骤3:每行组合(含共享图例)
对每行对齐后的子图,提取一个图例复用,将图与图例按比例组合,确保行内间距一致。
步骤4:拼接所有行
将每行的组合图垂直拼接,设置统一高度比例,实现整体紧密排列。
可复现代码(2×3布局示例)
library(ggplot2) library(cowplot) library(tidyterra) library(terra) # 生成示例栅格数据 r <- rast(system.file("ex/elev.tif", package = "terra")) r_list <- list( r1 = r, r2 = r * 1.2, r3 = r * 0.8, r4 = r + 50, r5 = r + 30, r6 = r - 20 ) # 定义基础绘图函数 plot_raster <- function(rast_obj, show_y = FALSE, show_title = FALSE, title_text = "") { p <- ggplot() + geom_spatraster(data = rast_obj) + scale_fill_viridis_c(option = "plasma") + theme_minimal() + theme( plot.margin = margin(5, 5, 5, 5), # 统一边距(单位:pt) plot.title = element_text(hjust = 0.5, size = 10), axis.text.x = element_blank(), axis.ticks.x = element_blank(), axis.title.x = element_blank() ) # 控制y轴显示 if (!show_y) { p <- p + theme( axis.text.y = element_blank(), axis.ticks.y = element_blank(), axis.title.y = element_blank() ) } else { p <- p + ylab("海拔(m)") } # 控制标题显示 if (show_title) { p <- p + ggtitle(title_text) } return(p) } # 生成所有子图 plots <- list( plot_raster(r_list$r1, show_y = TRUE, show_title = TRUE, "区域A"), plot_raster(r_list$r2, show_title = TRUE, "区域B"), plot_raster(r_list$r3, show_title = TRUE, "区域C"), plot_raster(r_list$r4, show_y = TRUE, "区域D"), plot_raster(r_list$r5, "区域E"), plot_raster(r_list$r6, "区域F") ) # 对齐所有子图的绘图区域 aligned_plots <- align_plots(plots = plots, align = "hv", axis = "tblr") # 提取图例(复用第一个图的图例) legend <- get_legend(aligned_plots[[1]] + theme(legend.position = "right")) # 组合第一行:图1+图2+图3 + 图例 row1 <- plot_grid( aligned_plots[[1]], aligned_plots[[2]], aligned_plots[[3]], rel_widths = c(1, 1, 1, 0.15), # 固定图例相对宽度 nrow = 1, align = "h" ) # 组合第二行:图4+图5+图6 + 图例 row2 <- plot_grid( aligned_plots[[4]], aligned_plots[[5]], aligned_plots[[6]], rel_widths = c(1, 1, 1, 0.15), nrow = 1, align = "h" ) # 组合所有行 final_plot <- plot_grid( row1, row2, nrow = 2, rel_heights = c(1, 1), align = "v" ) # 保存适配出版的结果 ggsave("final_raster_grid.png", final_plot, width = 12, height = 8, dpi = 300)
关键细节说明
- 统一边距:通过
theme(plot.margin)设置所有子图边距一致,避免默认边距差异导致的间距不均。 - 强制对齐:
align_plots(align = "hv")确保所有子图的绘图区域完全重叠对齐,不受轴标签、标题影响。 - 图例宽度控制:
rel_widths参数固定图例的相对宽度,避免图例大小干扰行内图的比例。 - 紧密排列:调整
plot.margin的数值可进一步缩小图间间距,适配出版空间限制。
内容的提问来源于stack exchange,提问作者Francis van Oordt
相关产品推荐
相关产品推荐

