A utility I think deserves more attention for this is the layOut formerly of th wq package (note the capital "O"). It's since been removed from the wq package, so I've put the code below and renamed it lay_out to match typical ggplot style. It is like base::layout in that the plots can be of varying sizes, laid out in rows and columns. Each argument to lay_out is a 3-element list consisting of the plot, the row indices in which to plot it, and the column indices in which to plot it.
For example, using @Paul McMurdie's plots,
lay_out(list(plot1, 1, 1),
list(plot2, 1, 2),
list(plot3, 2, 1),
list(plot4, 2, 2),
list(plot5, 3, 1:2),
list(plot6, 4, 1:2),
list(plot7, 1:2, 3))

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.)