rggplot2

Draw ggplots in the plot grid by column - plot_grid() function of the cowplot package


I am using the plot_grid() function of the cowplot package to draw ggplots in a grid and would like to know if there is a way to draw plots by column instead of by row?

library(ggplot2)
library(cowplot)

df <- data.frame(
    x = c(3,1,5,5,1),
    y = c(2,4,6,4,2)
)

# Create plots: say two each of path plot and polygon plot 
p <- ggplot(df)
p1 <- p + geom_path(aes(x,y)) + ggtitle("Path 1")
p2 <- p + geom_polygon(aes(x,y)) + ggtitle("Polygon 1")
p3 <- p + geom_path(aes(y,x)) + ggtitle("Path 2")
p4 <- p + geom_polygon(aes(y,x)) + ggtitle("Polygon 2")

plots <- list(p1,p2,p3,p4)
plot_grid(plotlist=plots, ncol=2) # plots are drawn by row

I would like to have plots P1 and P2 in the first column and p3 and p4 in the second column, something like:

plots <- list(p1, p3, p2, p4) # plot sequence changed
plot_grid(plotlist=plots, ncol=2)

Actually I could have 4, 6, or 8 plots. The number of rows in the plot grid will vary but will always have 2 columns. In each case I would like to fill the plot grid by column (vertically) so my first 2, 3, or 4 plots, as the case maybe, appear over each other. I would like to avoid hardcode these different permutations if I can specify something like par(mfcol = c(n,2)).


Solution

  • As you have observed, plot_grid() draws plots by row. I don't believe there's any way to change that, so if you want to maintain using plot_grid() (which would be probably most convenient), then one approach could be to change the order of the items in your list of plots to match what you need for plot_grid(), given knowledge of the number of columns.

    Here's a function I have written that does that. The basic idea is to:

    I've tried to build in a way to make this work even if the number of items in your list is not divisible by the intended number of columns (like a list of 8 items arranged in 3 columns).

    reorder_by_col <- function(myData, col_num) {
      x <- 1:length(myData)   # create index vector
      length(x) <- prod(dim(matrix(x, ncol=col_num)))  # adds NAs as necessary
      temp_matrix <- matrix(x, ncol=col_num, byrow = FALSE)
      new_x <- unlist(split(temp_matrix, rep(1:ncol(temp_matrix), each=row(temp_matrix))))
      names(new_x) <- NULL # not sure if we need this, but it forces an unnamed vector
      return(myData[new_x])
    }
    

    This all was written with a little help from Google and specifically answers to questions posted here and here.

    You can now see the difference without reordering:

    plots <- list(p1,p2,p3,p4)
    plot_grid(plotlist=plots, ncol=2)
    

    enter image description here

    ... and with reordering using the new method:

    newPlots <- reorder_by_col(myData=plots, col_num=2)
    plot_grid(plotlist=newPlots, ncol=2)
    

    enter image description here