I have used the method indicated here to align graphs sharing the same abscissa.
But I can\'t make it work when some of my graphs have a legend and others don\'t.
Thanks to this and that, posted in the comments (and then removed), I came up with the following general solution.
I like the answer from Sandy Muspratt and the egg package seems to do the job in a very elegant manner, but as it is "experimental and fragile", I preferred using this method:
#' Vertically align a list of plots.
#'
#' This function aligns the given list of plots so that the x axis are aligned.
#' It assumes that the graphs share the same range of x data.
#'
#' @param ... The list of plots to align.
#' @param globalTitle The title to assign to the newly created graph.
#' @param keepTitles TRUE if you want to keep the titles of each individual
#' plot.
#' @param keepXAxisLegends TRUE if you want to keep the x axis labels of each
#' individual plot. Otherwise, they are all removed except the one of the graph
#' at the bottom.
#' @param nb.columns The number of columns of the generated graph.
#'
#' @return The gtable containing the aligned plots.
#' @examples
#' g <- VAlignPlots(g1, g2, g3, globalTitle = "Alignment test")
#' grid::grid.newpage()
#' grid::grid.draw(g)
VAlignPlots <- function(...,
globalTitle = "",
keepTitles = FALSE,
keepXAxisLegends = FALSE,
nb.columns = 1) {
# Retrieve the list of plots to align
plots.list <- list(...)
# Remove the individual graph titles if requested
if (!keepTitles) {
plots.list <- lapply(plots.list, function(x) x <- x + ggtitle(""))
plots.list[[1]] <- plots.list[[1]] + ggtitle(globalTitle)
}
# Remove the x axis labels on all graphs, except the last one, if requested
if (!keepXAxisLegends) {
plots.list[1:(length(plots.list)-1)] <-
lapply(plots.list[1:(length(plots.list)-1)],
function(x) x <- x + theme(axis.title.x = element_blank()))
}
# Builds the grobs list
grobs.list <- lapply(plots.list, ggplotGrob)
# Get the max width
widths.list <- do.call(grid::unit.pmax, lapply(grobs.list, "[[", 'widths'))
# Assign the max width to all grobs
grobs.list <- lapply(grobs.list, function(x) {
x[['widths']] = widths.list
x})
# Create the gtable and display it
g <- grid.arrange(grobs = grobs.list, ncol = nb.columns)
# An alternative is to use arrangeGrob that will create the table without
# displaying it
#g <- do.call(arrangeGrob, c(grobs.list, ncol = nb.columns))
return(g)
}