如何合并内部使用graphics::layout的R绘图函数输出?
问题描述
我有一个实现复杂布局的绘图包装函数plot_fun,它内部使用graphics::layout,调用该函数会直接初始化新的绘图帧,不会返回grob或其他可存储对象。我希望将多个这类绘图(如simple_plot与plot_fun的输出)合并,让plot_fun的调用能像普通plot()调用一样被视为单个“绘图对象”。
尝试用par(mfrow = c(2, 1))布局时,plot_fun会破坏该布局。我猜测可以将绘图捕获为grob对象后用grid.arrange等工具实现合并,但希望找到简洁优雅的解决方案,而非处理内部用par(mfrow)绘图的hacky方法。
可复现代码
simple_plot <- function(col = "black") { plot(x = 1:10, y = 1:10, col = col) } ## wrapper function with a "complex" layout plot_fun <- function() { mat <- matrix(c(1, 2, 3, 4), nrow = 2, ncol = 2, byrow = TRUE) lay <- layout(mat = mat) simple_plot(col = "red") simple_plot(col = "blue") simple_plot(col = "green") simple_plot(col = "black") } par(mfrow = c(2, 1)) simple_plot() plot_fun() # simple_plot() would obviously work
解决方案
方法1:用recordPlot()捕获绘图并复用
recordPlot()可以捕获当前设备上的绘图内容,后续通过replayPlot()重新绘制。我们可以修改plot_fun,让它返回捕获的绘图对象:
# 修改plot_fun,返回捕获的绘图 plot_fun_capture <- function() { # 打开临时无输出设备捕获绘图 pdf(NULL) mat <- matrix(c(1, 2, 3, 4), nrow = 2, ncol = 2, byrow = TRUE) lay <- layout(mat = mat) simple_plot(col = "red") simple_plot(col = "blue") simple_plot(col = "green") simple_plot(col = "black") p <- recordPlot() dev.off() return(p) } # 组合绘图 par(mfrow = c(2, 1)) simple_plot() replayPlot(plot_fun_capture())
方法2:转成grob对象用grid布局组合
借助gridGraphics包将base绘图转为grob,再用gridExtra的grid.arrange()灵活组合,这种方式适配更多复杂布局场景:
library(gridGraphics) library(gridExtra) # 定义工具函数:将base绘图转为grob base_to_grob <- function(expr) { pdf(NULL) expr grid.echo() p <- grid.grab() dev.off() return(p) } # 生成两个绘图的grob对象 p1 <- base_to_grob(simple_plot()) p2 <- base_to_grob(plot_fun()) # 按2行1列布局组合 grid.arrange(p1, p2, nrow = 2)
方法3:修改plot_fun适配外层布局
如果希望完全在base绘图体系内解决,可以让plot_fun先保存当前布局参数,执行完后恢复,避免破坏外层的mfrow设置:
plot_fun_safe <- function() { # 保存当前所有par参数 old_par <- par(no.readonly = TRUE) on.exit(par(old_par)) # 函数退出时自动恢复参数 mat <- matrix(c(1, 2, 3, 4), nrow = 2, ncol = 2, byrow = TRUE) lay <- layout(mat = mat) simple_plot(col = "red") simple_plot(col = "blue") simple_plot(col = "green") simple_plot(col = "black") } # 正常使用mfrow布局 par(mfrow = c(2, 1)) simple_plot() plot_fun_safe()
内容的提问来源于stack exchange,提问作者Daniel Heimgartner
相关产品推荐
相关产品推荐

