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)).
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:
1:length(your_list)
),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)
... and with reordering using the new method:
newPlots <- reorder_by_col(myData=plots, col_num=2)
plot_grid(plotlist=newPlots, ncol=2)