Search code examples
rlayoutgraphicspar

Combining plots that use `graphics::layout` internally


  • Let's assume I have a wrapper function that generates a plot (writes to a graphics device) implementing a "complex" layout.
  • Calling the wrapper function inits a new graphics frame (i.e., it does not return a grob or any other object that can be stored).
  • So how could I combine multiple such plots?

Here is a reprex:

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
  • I would like the plot_fun() call to be treated similarly to a regular plot() call (as one "plot object") if this makes sense...
  • I think there is probably a work around to capture the plot as a grob object and then use grid.arrange() or similar.
  • This question has some parallels with how to combine plots that use par(mfrow = ...) internally (R | combine plots that use par(mfrow = ...) internally) - however, the solutions propsed there seem somewhat hacky and I wonder if there is a simple, elegant solution (or clarification why my approach is naive)...

Solution

  • You can capture base graphics and convert them to grid grobs using gridGraphics::echoGrob(). This is what the cowplot package uses under the hood.

    In your case, you would simply do:

    a <- gridGraphics::echoGrob(simple_plot)
    b <- gridGraphics::echoGrob(plot_fun)
    
    gridExtra::grid.arrange(a, b)
    

    enter image description here