Wednesday, March 3, 2010

Arrange multiple ggplot2 plots in the same image window

In a previous tutorial I showed you how to create plots faceted by the level of a third variable using ggplot2. A commenter asked about using faceted plots and viewports and reminded me of this function I found in the ggplot2 Google group. The arrange function below is similar to using par(mfrow=c(r,c)) in base graphics to put more than one plot in the same image window.
vp.layout <- function(x, y) viewport(layout.pos.row=x, layout.pos.col=y)
arrange <- function(..., nrow=NULL, ncol=NULL, as.table=FALSE) {
 dots <- list(...)
 n <- length(dots)
 if(is.null(nrow) & is.null(ncol)) { nrow = floor(n/2) ; ncol = ceiling(n/nrow)}
 if(is.null(nrow)) { nrow = ceiling(n/ncol)}
 if(is.null(ncol)) { ncol = ceiling(n/nrow)}
        ## NOTE see n2mfrow in grDevices for possible alternative
grid.newpage()
pushViewport(viewport(layout=grid.layout(nrow,ncol) ) )
 ii.p <- 1
 for(ii.row in seq(1, nrow)){
 ii.table.row <- ii.row 
 if(as.table) {ii.table.row <- nrow - ii.table.row + 1}
  for(ii.col in seq(1, ncol)){
   ii.table <- ii.p
   if(ii.p > n) break
   print(dots[[ii.table]], vp=vp.layout(ii.table.row, ii.col))
   ii.p <- ii.p + 1
  }
 }
}

The basic idea is that you assign ggplot2 plots to an object, and then use the arrange function to display two or more. Here's an example. First copy and paste the code above (or put in your Rprofile). Next install and/or load ggplot2 as described in a previous ggplot2 tutorial.
# Load the diamonds dataset
data(diamonds)

# Create a histogram, assign to "plot1"
plot1 <- qplot(price,data=diamonds,binwidth=1000)

# Create a scatterplot
plot2 <- qplot(carat,price,data=diamonds)

# Arrange and display the plots into a 2x1 grid
arrange(plot1,plot2,ncol=1)
And here's what you should get:

...

17 comments:

  1. Munawar CheemaMarch 3, 2010 2:25 PM

    wow that was fast :)

    ReplyDelete
  2. Also, check out imagemagick. It's a cross platform opensource image manipulation tool. It's really handy for stitching multiple images together. But the montage binary in your path, then call:

    montage image1.png image2.png -geometry -0-0 -tile 1x composite.png

    to stitch image1 and image2 together in a single column. Ideally all your images will be the same size. You can do this with lots of images using wildcards.

    ReplyDelete
  3. Great tip! I've been struggling with this aspect of ggplot2 for a while.

    ReplyDelete
  4. Great!! I was looking for something like this just today!

    ReplyDelete
  5. I started learning ggplot2 a couple weeks ago, so maybe I'm missing something. After I load the library(ggplot2), arrange() isn't showing up as a function. I tried loading library(ggplot), to see if it was in there, but still no luck.

    Any idea? ... I've been looking for this solution, but the no-arrange() is getting in the way.

    ReplyDelete
  6. Dan, the arrange function is not included with ggplot2. You have to copy and paste the code in the first box above to get it to work.

    ReplyDelete
  7. woohoo! works great! thanks

    ReplyDelete
  8. Great bit of code... But.. is there a way to output to a file?

    I've tried:-
    tmp<-arrange(mh3,mh4,mh1,mh2,ncol=1)
    ggsave(file="all.png",tmp)

    Thanks in advance

    ReplyDelete
  9. Jennie,

    I haven't had success with this either. Just use the GUI to save the image as PNG or PDF. I'll post a solution if I find one.

    Stephen

    ReplyDelete
  10. to save plots to file

    pdf("your_file.pdf",width = 11, height = 8)
    arrange(plot1,plot2,plot3,plot4,ncol=2)
    dev.off()

    ReplyDelete
  11. Hi,
    I get the following error when I do this.
    Error: attempt to apply non-function

    whats that about?

    ReplyDelete
  12. Hey guys, can you slap a license on your code? (BSD would be highly appreciated)

    ReplyDelete
  13. This comment has been removed by the author.

    ReplyDelete
  14. note that this function is included in the gridExtra package, with the name grid.arrange() and a few more options.

    ReplyDelete
  15. Great trick, thanks. How to go about having two plots share the same x-axis?

    ReplyDelete
  16. Thank you Stephen Turner. It has been great use your code. Thanks.

    ReplyDelete
  17. how do you control the space between the plots when using "arrange function"?

    ReplyDelete

Creative Commons License
Getting Genetics Done by Stephen Turner is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Based on a work at GettingGeneticsDone.blogspot.com.