Alasdair
Alasdair

Reputation: 1384

How can I create a list of plots to be rendered with ggplot?

I am trying to construct a list of ggplot graphics, which will be plotted later. What I have so far, using Anscombe's quartet for an example, is:

library(ggplot2)
library(gridExtra)
base <- ggplot() + xlim(4,19)
plots = vector(mode = "list", length = 4)
for(i in 1:4) {
  x <- anscombe[,i]
  y <- anscombe[,i+4]
  p <- geom_point(aes(x,y),colour="blue")
  q <- geom_smooth(aes(x,y),method="lm",colour="red",fullrange=T)
  plots[[i]] <- base+p+q
}
grid.arrange(grobs = plots,ncol=2)

As I travel through the loop, I want the current values of the plots p and q to be added with the base plot, into the i-th value of the list. That is, so that list element number i contains the plots relating to the i-th x and y columns from the dataset.

However, what happens is that the last plot only is drawn, four times. I've done something very similar with base R, using mfrow, plot and abline, so that I believe my logic is correct, but my implementation isn't. I suspect that the issue is with these lines:

plots = vector(mode = "list", length = 4)
plots[[i]] <- base+p+q

How can I create a list of ggplot graphics; starting with an empty list?

(If this is a trivial and stupid question, I apologise. I am very new both to R and to the Grammar of Graphics.)

Upvotes: 0

Views: 538

Answers (2)

Tech Commodities
Tech Commodities

Reputation: 1959

To force evaluation, there's a simple solution, change aes(...) into aes_(...) and your code works.

library(ggplot2)
library(gridExtra)
base <- ggplot() + xlim(4,19)
plots <- lapply(1:4, function(i) {
  x <- anscombe[,i]
  y <- anscombe[,i+4]
  p <- geom_point(aes_(x,y),colour="blue")
  q <- geom_smooth(aes_(x,y),method="lm",colour="red",fullrange=T)
  base+p+q
})
grid.arrange(grobs = plots,ncol=2)

enter image description here

Upvotes: 0

Gregor de Cillia
Gregor de Cillia

Reputation: 7685

The code works properly if lapply() is used instead of a for loop.

plots <- lapply(1:4, function(i) { 
  # create plot number i
})

The reason for this issue is that ggplot uses lazy evaluation. By the time the plots are rendered, the loop already iterated to i=4 and the last plot will be displayed four times.

Full working example:

library(ggplot2)
library(gridExtra)
base <- ggplot() + xlim(4,19)
plots <- lapply(1:4, function(i) {
  x <- anscombe[,i]
  y <- anscombe[,i+4]
  p <- geom_point(aes(x,y),colour="blue")
  q <- geom_smooth(aes(x,y),method="lm",colour="red",fullrange=T)
  base+p+q
})
grid.arrange(grobs = plots,ncol=2)

Upvotes: 1

Related Questions