When trying to call grid.arrange to put multiple plots on a same ggplot2 graph, I first build a list of the plots I want. Then I build the corresponding argument list to call grid.arrange, as was explained in a previous question. This is my code (my dataframe is called manip):
args.list <- NULL;
plot.list <- NULL;
for (m in names(manip[2:10])) {
plot.list <- c(plot.list, list(qplot(manip$side, y=manip[,m],ylab=m))
}
args.list <- c(plot.list, 1, 9)
names(args.list) <- c(names(manip)[2:10], list("nrow","ncol"))
do.call(grid.arrange, args.list)
This works, except that the 9 graphs are exactly the same! After checking, it turns out that the data is always the one corresponding to m=10
. So my guess was that the value of m
is not assigned in the loop, but evaluated later. However, the label ylab=m
is assigned correctly and is different for all the graphs.
So I don't really get what the difference is and how the interpreter chooses when to evaluate m for the plots. Can someone explain?
The behavior is due to the lazy evaluation of R.
Here is a minimal(?) example:
d <- 1:3
args.list <- NULL;
plot.list <- NULL;
for (m in 1:3) {
plot.list <- c(plot.list, list(qplot(d[m], d[m], ylab=letters[m])))
}
args.list <- c(plot.list, nrow=1, ncol=3)
do.call(grid.arrange, args.list)
in this case, d[m]
is evaluated at the call of do.call
. so m
is 3 for all panel.
here is a workaround:
d <- 1:3
args.list <- NULL;
plot.list <- NULL;
for (m in 1:3) {
plot.list <- c(plot.list,
list(qplot(d, d, data=data.frame(d=d[m]), ylab=letters[m])))
}
args.list <- c(plot.list, nrow=1, ncol=3)
do.call(grid.arrange, args.list)
in this case, d[m]
is evaluated at the call of qplot
, and the d[m]
is stored in the output object of qplot.
so, the simple solution is to pass data to qplot()
or ggplot()
.
I will first answer your question and then show an alternative using a facet plot.
Edited
The following, much simplified, code seems to work:
library(gridExtra)
manip <- mtcars
plot.list <- lapply(2:11,
function(x)qplot(manip$mpg, y=manip[, x],
ylab=names(manip)[x]))
do.call(grid.arrange, c(plot.list, nrow=10))
It produces this ugly plot:
Without knowing your objectives, it is dangerous to try and give advice, I know. Nonetheless, have you considered using facets for your plot instead?
The following code is much simpler, executes quiker and produces a graph that is easier to interpret:
library(reshape2)
manip <- mtcars
mmanip <- melt(manip, id.vars="mpg")
str(mmanip)
ggplot(mmanip, aes(x=mpg, y=value)) +
geom_point(stat="identity") +
facet_grid(.~variable, scales="free")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With