PJP
PJP

Reputation: 642

How to arrange plots in a single column using grid_arrange_shared_legend

I've been attempting to use the grid_arrange_shared_legend code to create a column of ggplot2 plots with a single legend (I can't use straight faceting because I need to use coord_flip and have different x-axis sizes - this has been documented by Hadley as not working - https://github.com/hadley/ggplot2/issues/95)

The code prints out the 4 plots as a 2x2 matrix with the legend underneath (see http://rpubs.com/sjackman/grid_arrange_shared_legend).

I have been trying to get the 4 plots plus legend in a single column, but failed miserably. Oddly enough, I assumed that the ncol=1 argument to grid.arrange would make it all a single column but it doesn't.

At present, given 4 graphs plus a legend, the code gives this layout:

+-----------+      +-----------+
|           |      |           |
|     1     |      |    3      |
|           |      |           |
+-----------+      +-----------+

+-----------+      +-----------+
|           |      |           |
|     2     |      |    4      |
|           |      |           |
+-----------+      +-----------+


        LEGEND HERE

I'm trying to get

+-----------+    
|           |   
|     1     |   
|           |    
+-----------+ 

+-----------+ 
|           |  
|     2     |  
|           |  
+-----------+ 

+-----------+    
|           |   
|     3     |   
|           |    
+-----------+ 

+-----------+ 
|           |  
|     4     |  
|           |  
+-----------+ 

 LEGEND HERE

Any help appreciated. Regards Pete

Upvotes: 3

Views: 455

Answers (1)

baptiste
baptiste

Reputation: 77096

this version has a column parameter for the layout of plots (the other ncol is to arrange the group of plots and legend)

grid_arrange_shared_legend <- function(..., ncol=1) {
  plots <- list(...)
  g <- ggplotGrob(plots[[1]] + theme(legend.position="bottom"))[["grobs"]]
  legend <- g[[which(sapply(g, function(x) x$name) == "guide-box")]]
  lheight <- sum(legend$height)
  grid.arrange(
    do.call(arrangeGrob, c(ncol=ncol, lapply(plots, function(x)
      x + theme(legend.position="none")))),
    legend,
    ncol = 1,
    heights = unit.c(unit(1, "npc") - lheight, lheight))
}

Alternatively, consider this strategy which will align the panels

library(gridExtra)

get_legend <- function(p, position="bottom"){
  g <- ggplotGrob(p + theme(legend.position=position))
  gtable::gtable_filter(g, "guide-box")
} 
strip_legend <- function(pl) lapply(pl, function(x) x + theme(legend.position="none"))

legend <- get_legend(p1)
pl <- strip_legend(list(p1,p2,p3,p4))
gl <- lapply(pl, ggplotGrob)
lheight <- sum(legend$heights)
grid.arrange(do.call(rbind, gl), legend, 
             heights = unit.c(unit(1,"npc") - lheight, lheight))

enter image description here

Upvotes: 4

Related Questions