如何绘制含三个同尺寸ggplot2子图且仅显示单个图例的面板?
解决方法
有两种简洁的方式可以实现单图例+子图同尺寸的需求:
方法一:使用patchwork包(推荐)
patchwork是专门用于ggplot2图形组合的工具,自带图例收集功能,代码更简洁直观:
首先安装并加载patchwork:
install.packages("patchwork") library(patchwork)
保留你原来的子图代码,直接组合并收集图例:
library(terra) library(ggplot2) library(tidyterra) v <- vect(system.file("ex/lux.shp", package = "terra")) p1 <- ggplot(v) + geom_spatvector(aes(fill = NAME_2), color = "grey") + borders() + coord_sf(xlim = c(4, 8), ylim = c(49, 49.5)) p2 <- ggplot(v) + geom_spatvector(aes(fill = NAME_2), color = "grey") + borders() + coord_sf(xlim = c(4, 8), ylim = c(49.5, 50)) p3 <- ggplot(v) + geom_spatvector(aes(fill = NAME_2), color = "grey") + borders() + coord_sf(xlim = c(4, 8), ylim = c(50, 50.5)) # 垂直堆叠子图并合并图例 p1 / p2 / p3 + plot_layout(guides = "collect")
p1 / p2 / p3表示将三个图垂直排列,guides = "collect"会自动把重复的图例合并为一个,子图会自动调整为相同尺寸。你还可以通过plot_annotation()添加整体标题等元素。
方法二:使用gridExtra包(适配原grid.arrange方案)
如果坚持使用grid.arrange,需要先移除子图的图例,再单独提取图例进行组合:
- 修改子图,去掉各自的图例:
p1_noleg <- p1 + theme(legend.position = "none") p2_noleg <- p2 + theme(legend.position = "none") p3_noleg <- p3 + theme(legend.position = "none")
- 从任意一个原始子图中提取单个图例:
# 定义提取图例的辅助函数 get_legend <- function(myggplot){ tmp <- ggplot_gtable(ggplot_build(myggplot)) leg_index <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box") legend <- tmp$grobs[[leg_index]] return(legend) } single_legend <- get_legend(p1)
- 组合无图例的子图和单独的图例:
library(gridExtra) grid.arrange( arrangeGrob(p1_noleg, p2_noleg, p3_noleg, ncol = 1), single_legend, ncol = 2, widths = c(4, 1) # 调整主图区域与图例的宽度比例,确保子图尺寸一致 )
内容的提问来源于stack exchange,提问作者Tpellirn
相关产品推荐
相关产品推荐

