Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating arbitrary panes in ggplot2

Tags:

r

ggplot2

In base graphics I can create a 4 panel pane of graphics by doing the following:

par(mfrow=c(2,2))
for (i in 1:4){
  plot(density(rnorm(100)))
}

which results in

enter image description here

I'd like to do the same sort of thing with ggplot2, but I can't figure out how to do it. I can't use facets because my real data, unlike this trivial example, is in very different structures and I want two graphs to be point charts and two to be histograms. How can do create panels or panes in ggplot2?

like image 387
JD Long Avatar asked Nov 03 '11 10:11

JD Long


2 Answers

Following Josh O'Brien's example: I'm surprised no one has mentioned grid.arrange from the gridExtra package yet:

library(gridExtra)
grid.arrange(q1,q2,q3,q4,q5,q6,nrow=3)

This seems to be mentioned here: multiple graphs in one canvas using ggplot2

For me, it's much easier than remembering all the viewport stuff.

like image 94
Ben Bolker Avatar answered Nov 13 '22 11:11

Ben Bolker


EDIT: { Ben Bolker points to an even better option -- grid.arrange from the gridExtra package. If you're a ggplot2 user, though, the R Cookbook site is still worth a click-through. }

There's code for a nice multiplot function on this page of the R Cookbook (definitely worth a visit) that's useful for this sort of thing. Quoting directly from that site:

multiplot <- function(..., plotlist=NULL, cols) {
    require(grid)

    # Make a list from the ... arguments and plotlist
    plots <- c(list(...), plotlist)

    numPlots = length(plots)

    # Make the panel
    plotCols = cols                       # Number of columns of plots
    plotRows = ceiling(numPlots/plotCols) # Number of rows needed, calculated from # of cols

    # Set up the page
    grid.newpage()
    pushViewport(viewport(layout = grid.layout(plotRows, plotCols)))
    vplayout <- function(x, y)
        viewport(layout.pos.row = x, layout.pos.col = y)

    # Make each plot, in the correct location
    for (i in 1:numPlots) {
        curRow = ceiling(i/plotCols)
        curCol = (i-1) %% plotCols + 1
        print(plots[[i]], vp = vplayout(curRow, curCol ))
    }

}

Trying it out with 6 plots in a 3-by-2 layout (four of JD Long's plots, and two bonus ones!):

set.seed(2)
q1 <- ggplot(data.frame(x=rnorm(50)), aes(x)) + geom_density()
q2 <- ggplot(data.frame(x=rnorm(50)), aes(x)) + geom_density()
q3 <- ggplot(data.frame(x=rnorm(50)), aes(x)) + geom_density()
q4 <- ggplot(data.frame(x=rnorm(50)), aes(x)) + geom_density()
q5 <- ggplot(data.frame(x=rnorm(50)), aes(x)) + geom_density()
q6 <- ggplot(data.frame(x=rnorm(50)), aes(x)) + geom_density()

multiplot(q1, q2, q3, q4, q5, q6, cols=2)

gives this figure:

enter image description here

If the function doesn't quite fit your needs, at least it gives you a nice starting point!

like image 19
Josh O'Brien Avatar answered Nov 13 '22 12:11

Josh O'Brien