使用patchwork与ggplot2在R Markdown PDF中填充页面的问题
Patchwork排版地图的空白问题解决方案
我尝试用patchwork库排列3幅地图并输出PDF,要求组合后的地图占满6.5英寸的页面宽度,最大化单幅地图尺寸。单独绘图时地图能正常占满指定空间,但用patchwork排版后出现大量空白,调整边距的方法无效;同时还希望消除组合图中上方两幅图与下方图之间的空白。可复现代码及原效果如下:
原代码(含问题的组合绘图)
YAML文档头
--- title: "Testing" author: "Erica Newton" date: "2023-06-23" output: pdf_document ---
加载依赖包与数据
library(ggspatial) library(ggplot2) library(patchwork) library(sf) library(terra) library(raster) library(tidyterra) library(dismo) nc <- st_read(system.file("shape/nc.shp", package = "sf")) b2 <- rast(system.file("ex/bio16.grd", package = "dismo"))
单独绘图(正常响应宽高)
a <- ggplot(nc) + geom_sf() + scale_x_continuous(expand = c(0,0)) + scale_y_continuous(expand = c(0,0)) + theme_void() b <- ggplot(nc) + scale_x_continuous(expand = c(0,0)) + scale_y_continuous(expand = c(0,0)) + geom_sf(fill = "pink") + theme_void() (a + a) / b
c <- ggplot() + geom_spatraster(data = b2) + scale_x_continuous(expand = c(0,0)) + scale_y_continuous(expand = c(0,0)) + theme_void() + theme(legend.position = "none", plot.margin = unit(c(0, 0, 0, 0), "null"), panel.background = element_rect(fill = "lightblue")) c
存在空白问题的组合绘图
(a + b) / c + plot_annotation(theme = theme(plot.margin = margin()))
原效果截图

修正方案
核心问题原因
- 坐标系不匹配:
nc(sf矢量数据)与b2(栅格数据)的坐标系不同,导致排版时比例错位,产生空白。 - 边距未彻底清除:仅单独设置子图边距或整体边距,未统一所有层级的边距设置。
修正后的完整代码
library(ggspatial) library(ggplot2) library(patchwork) library(sf) library(terra) library(raster) library(tidyterra) library(dismo) nc <- st_read(system.file("shape/nc.shp", package = "sf")) b2 <- rast(system.file("ex/bio16.grd", package = "dismo")) # 统一坐标系:将矢量数据转换为栅格数据的坐标系 nc <- st_transform(nc, st_crs(b2))
a <- ggplot(nc) + geom_sf() + scale_x_continuous(expand = c(0,0)) + scale_y_continuous(expand = c(0,0)) + theme_void() b <- ggplot(nc) + scale_x_continuous(expand = c(0,0)) + scale_y_continuous(expand = c(0,0)) + geom_sf(fill = "pink") + theme_void() c <- ggplot() + geom_spatraster(data = b2) + scale_x_continuous(expand = c(0,0)) + scale_y_continuous(expand = c(0,0)) + theme_void() + theme(legend.position = "none", panel.background = element_rect(fill = "lightblue")) # 修正后的组合排版 (a + b) / c + # 设置上下部分高度比例,消除中间空白 plot_layout(heights = c(1, 1)) + # 清除组合图整体的外部边距 plot_annotation(theme = theme(plot.margin = margin(0, 0, 0, 0))) + # 统一所有子图的内部边距为0 & theme(plot.margin = unit(c(0, 0, 0, 0), "pt"))
修正要点
- 统一坐标系:用
st_transform()将矢量数据nc转换为与栅格数据b2相同的坐标系,确保所有地图的比例一致,避免错位空白。 - 统一边距设置:通过
&运算符为所有子图设置plot.margin = unit(c(0,0,0,0), "pt"),彻底清除子图内部边距;同时在plot_annotation()中清除组合图的外部边距。 - 调整布局比例:使用
plot_layout(heights = c(1,1))指定上下两部分的高度比例,让上下图紧密贴合,消除中间的空白区域。
内容的提问来源于stack exchange,提问作者Nova
相关产品推荐
相关产品推荐

