Align multiple plots in ggplot2 when some have legends and others don't

前端 未结 6 1459
离开以前
离开以前 2020-11-30 03:09

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.

6条回答
  •  情话喂你
    2020-11-30 03:56

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

提交回复
热议问题