如何使用coord_equal()垂直对齐不同高度的分面ggplot图表?
我太懂这个坑了!当你给带coord_equal()的分面ggplot做垂直拼接时,原本好用的egg::ggarrange()无分面方案直接“罢工”,还会出现y轴单位是x轴两倍的尴尬情况——本质是分面后图表的整体尺寸计算逻辑变了,默认的参数没跟上分面行数的差异。
咱们先拿一个可复现的例子来演示问题,再一步步解决:
第一步:准备测试代码
先做两个带coord_equal()的分面图,模拟你的场景:
library(ggplot2) library(egg) library(cowplot) library(patchwork) # 省心备选工具 # 生成分面数据 df1 <- expand.grid(x = 1:10, y = 1:10, facet = c("A", "B")) df1$value <- rnorm(nrow(df1)) df2 <- expand.grid(x = 1:10, y = 1:10, facet = c("C", "D", "E")) df2$value <- rnorm(nrow(df2)) # 带coord_equal()的分面图 p1 <- ggplot(df1, aes(x, y, fill = value)) + geom_tile() + facet_wrap(~facet, ncol = 2) + # 2列1行分面 coord_equal() p2 <- ggplot(df2, aes(x, y, fill = value)) + geom_tile() + facet_wrap(~facet, ncol = 3) + # 3列1行分面 coord_equal()
如果你直接用ggarrange(p1, p2, ncol = 1),会发现p1的y轴单位明显比x轴大——因为默认的高度分配是1:1,但p1的面板高度被压缩了,破坏了coord_equal()的1:1宽高比。
第二步:核心解决方案:按分面行数分配高度
coord_equal()要求每个面板的宽高比是1:1,所以整个图表的总高度应该等于「单面板高度 × 分面行数」。咱们只需要按两个图的分面行数比例来设置拼接高度,就能保住每个面板的比例,同时实现垂直对齐。
方法1:用egg::ggarrange()实现
先提取两个图的分面行数,再设置heights参数:
# 直接从facet参数里获取分面行数 nrow_p1 <- p1$facet$params$nrow nrow_p2 <- p2$facet$params$nrow # 按行数比例设置高度,同时开启垂直对齐 ggarrange(p1, p2, ncol = 1, heights = c(nrow_p1, nrow_p2), align = "v")
方法2:用cowplot::plot_grid()实现
逻辑和上面一致,用rel_heights参数设置相对高度:
plot_grid(p1, p2, ncol = 1, rel_heights = c(nrow_p1, nrow_p2), align = "v")
方法3:用patchwork(更省心的备选)
patchwork对分面和coord_equal()的兼容性极好,几乎不用手动计算:
# 直接用/拼接,自动对齐,加上行数比例的高度设置 p1 / p2 + plot_layout(heights = c(nrow_p1, nrow_p2))
关键原理:为什么之前失效?
无分面时,图表的宽高比直接由coord_equal()控制;但分面后,图表总高度是「分面行数 × 单面板高度」,默认的拼接工具会把两个图的总高度设为1:1,导致分面行数多的图里,每个面板的高度被压缩,破坏了1:1的比例,看起来就是y轴单位变大了。
只要按分面行数分配总高度,每个面板的宽高比就能维持1:1,y轴和x轴单位也就一致了。
内容的提问来源于stack exchange,提问作者Kevin
相关产品推荐
相关产品推荐

