Reputation: 2358
I'm iterating through some data creating lists of ggplot
graphics that I want to print together on a single image. My code has two loops, one inside the other. The outer loop subdivides the data based on one variable. The inner loop subdivides the data further and produces a scatterplot for each subdivision; the plots are saved in a list. Once the inner loop has completed, a grid.arrange object is created using list objects like this (NOTE: This code includes a custom function, my_scatter
that is shared at the bottom of this question):
require(ggplot2)
require(grid)
require(gridExtra)
PRIMARY LOOP STRUCTURE {
...
my_plots = list()
for (j in c(1:length(my_nodes))){
cur_node = my_nodes[j]
node_dat = temp_dat[temp_dat$Node == cur_node,]
p = my_scatter(node_dat, "PRE", "POST") + geom_point(aes(color = Node, shape = Recurrence_Type, size = 2))
my_plots[[j]] = p
}
grid.arrange(my_plots[[1]],my_plots[[2]],my_plots[[3]],my_plots[[4]],my_plots[[5]], nrow = 4, ncol = 3)
}
The problem is that for some iterations of the loop, my_plots
will have a different number of elements. I know that I could solve this problem with a series of conditional statements:
if (length(my_plots) == 2) {
grid.arrange(my_plots[[1]],my_plots[[2]],nrow=1,ncol=2)
} elsif ( length(my_plots == 3) {
grid.arrange(my_plots[[1]],my_plots[[2]],nrow=2,ncol=2)
} elsif...
But this seems cumbersome and I am hoping to find a less blunt solution. Ordinarily I would use facet_grid()
for this kind of thing but the scatter plots are difficult to interpret when they are distorted into the ultra thin rectangles facet_grid produces when it has more than 2 or 3 plots to produce.
I see that this question seems to solve the problem using grobs
and lapply
- which are two aspects of R programming I've never had much success with in the past.
How can I either:
Here's the function my_scatter
used in the first code block:
my_scatter = function (df,a,b) {
test1 = class(df)
if (! test1 == "data.frame") {
stop("1st Variable should be a data frame")
}
test2 = class(df[,a])
valid_classes = c("integer", "numeric")
if (! test2 %in% valid_classes) {
stop("2nd Variable should either be an integer or numeric")
}
test3 = class(df[,b])
if (! test3 %in% valid_classes) {
stop("3rd Variable should either have class numeric or integer")
}
p = ggplot(data = df, aes_string(a, b)) + xlim(0,1) + ylim(0,1) + geom_point() + geom_abline(slope = 1, intercept = 0, color = "white")
return(p)
}
Upvotes: 5
Views: 7690
Reputation: 77096
grid.arrange(grobs = my_plots)
should do the trick. You don't need to convert the plots to grobs, grid.arrange does it for you. But if you had to, you could do:
my_grobs = lapply(my_plots, ggplotGrob)
Upvotes: 12