如何在网格排布中对齐带独立图例的分面与单个ggplot geom_raster栅格图
不对齐的根本原因
之前试的三种排布方法没用,是因为所有工具默认都是按整块图的外轮廓矩形比例分配画布空间,就算给工具加上水平、垂直对齐的参数,也只是对齐两个图块的外轮廓边缘,从来没有强制统一两个图内部的核心栅格绘图区的物理尺寸:
- 带双分面的g1,两个栅格面板在
coord_fixed()的约束下,会跟着画布自动缩放 - 单幅的g2,栅格面板同样跟着画布自动缩放
两个图各自带的图例、标题、分面条带这些外围元素的宽度占比不一样,就算你把图块总宽度设成2:1,也只是给两个图的外轮廓矩形分空间,碰不到内部的核心面板,自然会出现高低、宽窄对不上的问题。
可直接落地的解决方法
核心逻辑很简单:先把两个图里的栅格面板物理尺寸强制改成完全一样,再做排布。毕竟两个栅格的原始范围完全一致(x从0到100,y从0到150),在固定坐标比例下本来就该是等大的绘图块,手动调整grob里的面板尺寸参数就行,不用靠排布工具自动算。
可直接复制运行的修复代码:
# 加载grob处理依赖 library(gtable) library(grid) # 把两个ggplot转成可编辑的grob对象 g1_grob <- ggplotGrob(g1) g2_grob <- ggplotGrob(g2) # 提取g1里单块分面的尺寸(两个分面尺寸完全相同) g1_panel_pos <- g1_grob$layout[g1_grob$layout$name == "panel", ][1, ] # 锁定单块面板的高度、宽度参数 fixed_panel_h <- g1_grob$heights[g1_panel_pos$t:g1_panel_pos$b] fixed_panel_w <- g1_grob$widths[g1_panel_pos$l:g1_panel_pos$r] # 把g2的面板尺寸强制改成和g1的分面面板完全一致 g2_panel_pos <- g2_grob$layout[g2_grob$layout$name == "panel", ][1, ] g2_grob$heights[g2_panel_pos$t:g2_panel_pos$b] <- fixed_panel_h g2_grob$widths[g2_panel_pos$l:g2_panel_pos$r] <- fixed_panel_w # 画布按比例排布 grid.newpage() pushViewport(viewport(layout = grid.layout( nrow = 1, ncol = 2, widths = unit(c(2.2, 1.1), "null") # 微调宽度值适配各自图例的占位空间 ))) # 左侧画g1 pushViewport(viewport(layout.pos.row = 1, layout.pos.col = 1)) grid.draw(g1_grob) popViewport() # 右侧画g2 pushViewport(viewport(layout.pos.row = 1, layout.pos.col = 2)) grid.draw(g2_grob) popViewport()
操作提醒
- 这套方法完全保留两个图独立的fill色阶图例,差值栅格的数值范围不会被主栅格稀释,完全满足你要保留差值数值特征的需求
- 不需要靠排布工具的自动对齐功能,因为核心面板的尺寸已经被强制锁死,不会再出现缩放后的错位
- 如果需要微调对齐精度,只需要修改锁定的面板尺寸参数就行,不用大改之前写好的主题设置
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

