It\'s relatively simple using grid.arrange in the gridExtra package to arrange multiple plots in a matrix, but how can you arrange plots (the ones
I like the interface provided by the lay_out function (formerly in the wq package) . It takes arguments of the form list(plot, row(s), column(s)). For your example:
lay_out(list(p1, 1:2, 1:3),
list(p2, 1, 4),
list(p3, 1, 5),
list(p4, 2, 4),
list(p5, 2, 5),
list(p6, 3, 1),
list(p7, 3, 2),
list(p8, 3, 3),
list(p9, 3, 4:5))
Which yields:

lay_out = function(...) {
x <- list(...)
n <- max(sapply(x, function(x) max(x[[2]])))
p <- max(sapply(x, function(x) max(x[[3]])))
grid::pushViewport(grid::viewport(layout = grid::grid.layout(n, p)))
for (i in seq_len(length(x))) {
print(x[[i]][[1]], vp = grid::viewport(layout.pos.row = x[[i]][[2]],
layout.pos.col = x[[i]][[3]]))
}
}
(Code sourced from a prior version of the wq package, from the commit history on the unofficial Github CRAN mirror.)