Combined plot of ggplot2 (Not in a single Plot), using par() or layout() function? [duplicate]
I've been thinking of using par() or layout() functions for combining ggplots. Will it be possible to use those functions?
Say I want to plot ggplot for scatterplot and ggplot for histogram. And I want to combine the two plots (NOT IN A SINGLE PLOT). Is it applicable?
I tried it with simple plotting in R, without using the ggplot functions. And it works actually.
Here's a sample from Quick-R, Link: http://www.statmethods.net/advgraphs/layout.html
# 4 figures arranged in 2 rows and 2 columns
attach(mtcars)
par(mfrow=c(2,2))
plot(wt,mpg, main="Scatterplot of wt vs. mpg")
plot(wt,disp, main="Scatterplot of wt vs disp")
hist(wt, main="Histogram of wt")
boxplot(wt, main="Boxplot of wt")
# One figure in row 1 and two figures in row 2
attach(mtcars)
layout(matrix(c(1,1,2,3), 2, 2, byrow = TRUE))
hist(wt)
hist(mpg)
hist(disp)
But when I try to use ggplot, and combine the plot, I don't get an output.
library(ggplot2)
library(grid)
vplayout <- function(x, y) viewport(layout.pos.row = x, layout.pos.col = y)
plot1 <- qplot(mtcars,x=wt,y=mpg,geom="point",main="Scatterplot of wt vs. mpg")
plot2 <- qplot(mtcars,x=wt,y=disp,geom="point",main="Scatterplot of wt vs disp")
plot3 <- qplot(wt,data=mtcars)
plot4 <- qplot(wt,mpg,data=mtcars,geom="boxplot")
plot5 <- qplot(wt,data=mtcars)
plot6 <- qplot(mpg,data=mtcars)
plot7 <- qplot(disp,data=mtcars)
# 4 figures arranged in 2 rows and 2 columns
grid.newpage()
pushViewport(viewport(layout = grid.layout(2, 2)))
print(plot1, vp = vplayout(1, 1))
print(plot2, vp = vplayout(1, 2))
print(plot3, vp = vplayout(2, 1))
print(plot4, vp = vplayout(2, 2))
# One figure in row 1 and two figures in row 2
grid.newpage()
pushViewport(viewport(layout = grid.layout(2, 2)))
print(plot5, vp = vplayout(1, 1:2))
print(plot6, vp = vplayout(2, 1))
print(plot7, vp = vplayout(2, 2))
A utility I think deserves more attention for this is the layOut
formerly of th wq
package (note the capital "O"). It's since been removed from the wq
package, so I've put the code below and renamed it lay_out
to match typical ggplot style. It is like base::layout
in that the plots can be of varying sizes, laid out in rows and columns. Each argument to lay_out
is a 3-element list consisting of the plot, the row indices in which to plot it, and the column indices in which to plot it.
For example, using @Paul McMurdie's plots,
lay_out(list(plot1, 1, 1),
list(plot2, 1, 2),
list(plot3, 2, 1),
list(plot4, 2, 2),
list(plot5, 3, 1:2),
list(plot6, 4, 1:2),
list(plot7, 1:2, 3))
lay_out = function(...) {
x <- list(...)
n <- max(sapply(x, function(x) max(x[[2]])))
p <- max(sapply(x, function(x) max(x[[3]])))
grid::pushViewport(grid::viewport(layout = grid::grid.layout(n, p)))
for (i in seq_len(length(x))) {
print(x[[i]][[1]], vp = grid::viewport(layout.pos.row = x[[i]][[2]],
layout.pos.col = x[[i]][[3]]))
}
}
(Code sourced from a prior version of the wq
package, from the commit history on the unofficial Github CRAN mirror.)
The answer involving grid.layout
works, I've used it, and I up-voted it. However, I usually find this solution much too tedious and error-prone, and I suspect most ggplot2 enthusiasts that do this regularly have wrapped this up in a function. I have found several such wrapping functions in previous searches, but my current workhorse solution is in a grid addon package called gridExtra
. It has useful arguments, but the default rows/columns setup is often what you wanted in the first place:
library("ggplot2")
# Generate list of arbitrary ggplots
plot1 <- qplot(data = mtcars, x=wt, y=mpg, geom="point",main="Scatterplot of wt vs. mpg")
plot2 <- qplot(data = mtcars, x=wt, y=disp, geom="point",main="Scatterplot of wt vs disp")
plot3 <- qplot(wt,data=mtcars)
plot4 <- qplot(wt,mpg,data=mtcars,geom="boxplot")
plot5 <- qplot(wt,data=mtcars)
plot6 <- qplot(mpg,data=mtcars)
plot7 <- qplot(disp,data=mtcars)
# You might have produced myPlotList using instead lapply, mc.lapply, plyr::dlply, etc
myPlotList = list(plot1, plot2, plot3, plot4, plot5, plot6, plot7)
library("gridExtra")
do.call(grid.arrange, myPlotList)
Notice how the actual "combine my plots into one graphic" code was one line (after loading gridExtra). You might argue that putting the plots into a list was an extra line, but actually I could have alternatively used
grid.arrange(plot1, plot2, plot3, plot4, plot5, plot6, plot7)
For small numbers of ggplots this might be preferable. However, for n_plots > 4
you will begin to resent having to name and type them all.