Search code examples
rplotggplot2grid-layoutcowplot

R 'cowplot' neatly produce gridded plot with shared (common) legends and unique legends


See my related question and the accepted answer here.

I am trying to produce a plot similar to that in the accepted answer i.e. a gridded plot with a shared common legend and a different unique legend attached to each plot on the grid.

Specifically, I want a 3 row, 1 column grid with 1 plot on each row. Like this:

enter image description here

Which was produced with the following code:

  library (ggplot2)
  library(gridExtra)
  library (grid)
  library(cowplot)


   diamonds2 <- diamonds[sample(nrow(diamonds), 500), ]

   # 3 ggplot plot objects with multiple legends 1 common legend and 3 unique legends

  p1<- ggplot(diamonds2, aes(x=price, y= depth, color= clarity , shape= cut )) +
geom_point(size=5) + labs (shape = "unique legend", color = "common legend")

  p2 <- ggplot(diamonds2, aes(x=price, y= depth, color= clarity , shape=   color )) +
geom_point(size=5) + labs (shape = "unique legend", color = "common legend")

  p3 <- ggplot(diamonds2, aes(x=price, y= depth, color= clarity , shape= clarity )) +
geom_point(size=5) + labs (shape = "unique legend", color = "common legend")

  cowplot::plot_grid(
  cowplot::plot_grid(
  p1 + scale_color_discrete(guide = FALSE),
  p2 + scale_color_discrete(guide = FALSE),
  p3 + scale_color_discrete(guide = FALSE),
  nrow=3, ncol = 1))

But with a shared legend which relates to the color = argument of each plot object.

I've tried many variations of the below code and have added/adjusted/removed various arguments/parameters in consultation with the cowplot documentation but I cannot get a neat plot like the one above with the shared legend at the bottom (or anywhere useful!) - everything I have attempted returns a crowded plot like below.

Adaption of the above code to include the shared legend :

  cowplot::plot_grid(
   cowplot::plot_grid(
    p1 + scale_color_discrete(guide = FALSE),
    p2 + scale_color_discrete(guide = FALSE),
    p3 + scale_color_discrete(guide = FALSE),
    nrow=3, ncol = 1
   ),
   cowplot::get_legend(p1 + scale_shape(guide = FALSE) +   theme(legend.position = "bottom")), nrow=3)

Which results in a crowded plot like this with a lot of empty space:

enter image description here

Could anyone suggest where I might be going wrong?


Solution

  • Each call to plot_grid splits your plotting area. Here, you are nesting two calls to plot_grid, and you are asking for 3 rows in each. cowplot therefore splits the plotting area in two equal parts:

    • in the top part, it puts your scatter plot
    • in the bottom part, your legend takes the first row, with nothing in the bottom two rows creating a lot of empty space while squishing your scatter plots.

    You can specify the relative height of each of your plotting area giving more space for the scatter plots, and less space for the legend at the bottom. For instance for 85% plots, and 15% legend:

    cowplot::plot_grid(
       cowplot::plot_grid(
        p1 + scale_color_discrete(guide = FALSE),
        p2 + scale_color_discrete(guide = FALSE),
        p3 + scale_color_discrete(guide = FALSE),
        ncol = 1, align = "v"
       ),
       cowplot::get_legend(p1 + scale_shape(guide = FALSE) + 
          theme(legend.position = "bottom")),
       ncol=1, rel_heights=c(.85, .15))
    

    which produces :

    enter image description here