I would like to place two plots side by side using the ggplot2 package, i.e. do the equivalent of
For example, I would like to have the following two plots show side-by-side with the same scale.
x <- rnorm(100) eps <- rnorm(100,0,.2) qplot(x,3*x+eps) qplot(x,2*x+eps)
Do I need to put them in the same data.frame?
qplot(displ, hwy, data=mpg, facets = . ~ year) + geom_smooth()
grid.arrange() in the
gridExtra package will combine multiple plots; this is how you put two side by side.
require(gridExtra) plot1 <- qplot(1) plot2 <- qplot(1) grid.arrange(plot1, plot2, ncol=2)
This is useful when the two plots are not based on the same data, for example if you want to plot different variables without using reshape().
This will plot the output as a side effect. To print the side effect to a file, specify a device driver (such as
png, etc), e.g.
pdf("foo.pdf") grid.arrange(plot1, plot2) dev.off()
arrangeGrob() in combination with
ggsave("foo.pdf", arrangeGrob(plot1, plot2))
This is the equivalent of making two distinct plots using
par(mfrow = c(1,2)). This not only saves time arranging data, it is necessary when you want two dissimilar plots.
Facets are helpful for making similar plots for different groups. This is pointed out below in many answers below, but I want to highlight this approach with examples equivalent to the above plots.
mydata <- data.frame(myGroup = c('a', 'b'), myX = c(1,1)) qplot(data = mydata, x = myX, facets = ~myGroup) ggplot(data = mydata) + geom_bar(aes(myX)) + facet_wrap(~myGroup)
plot_grid function in the
cowplot is worth checking out as an alternative to
grid.arrange. See the answer by @claus-wilke below and this vignette for an equivalent approach; but the function allows finer controls on plot location and size, based on this vignette.
One downside of the solutions based on
grid.arrange is that they make it difficult to label the plots with letters (A, B, etc.), as most journals require.
I wrote the cowplot package to solve this (and a few other) issues, specifically the function
library(cowplot) iris1 <- ggplot(iris, aes(x = Species, y = Sepal.Length)) + geom_boxplot() + theme_bw() iris2 <- ggplot(iris, aes(x = Sepal.Length, fill = Species)) + geom_density(alpha = 0.7) + theme_bw() + theme(legend.position = c(0.8, 0.8)) plot_grid(iris1, iris2, labels = "AUTO")
The object that
plot_grid() returns is another ggplot2 object, and you can save it with
ggsave() as usual:
p <- plot_grid(iris1, iris2, labels = "AUTO") ggsave("plot.pdf", p)
Alternatively, you can use the cowplot function
save_plot(), which is a thin wrapper around
ggsave() that makes it easy to get the correct dimensions for combined plots, e.g.:
p <- plot_grid(iris1, iris2, labels = "AUTO") save_plot("plot.pdf", p, ncol = 2)
ncol = 2 argument tells
save_plot() that there are two plots side-by-side, and
save_plot() makes the saved image twice as wide.)
One frequent point of confusion is that the cowplot package changes the default ggplot2 theme. The package behaves that way because it was originally written for internal lab uses, and we never use the default theme. If this causes problems, you can use one of the following three approaches to work around them:
1. Set the theme manually for every plot. I think it's good practice to always specify a particular theme for each plot, just like I did with
+ theme_bw() in the example above. If you specify a particular theme, the default theme doesn't matter.
2. Revert the default theme back to the ggplot2 default. You can do this with one line of code:
3. Call cowplot functions without attaching the package. You can also not call
require(cowplot) and instead call cowplot functions by prepending
cowplot::. E.g., the above example using the ggplot2 default theme would become:
## Commented out, we don't call this # library(cowplot) iris1 <- ggplot(iris, aes(x = Species, y = Sepal.Length)) + geom_boxplot() iris2 <- ggplot(iris, aes(x = Sepal.Length, fill = Species)) + geom_density(alpha = 0.7) + theme(legend.position = c(0.8, 0.8)) cowplot::plot_grid(iris1, iris2, labels = "AUTO")