Search code examples
rloopsggplot2assign

Using assign within ggplot loop gives incorrect plots


I'm creating three plots in a loop over I and using assign to save each plot. The y variable is scaled by the loop index. The scaling should ensure that the final panel of plots each has y going from 0 to 1. This isn't happening and the plots seem to be being changed as the loop runs. I'd be grateful if someone could explain this apparently odd behaviour.

enter image description here

library(dplyr)
library(ggplot2)
library(gridExtra)

loci = c(1,2,3)
x <- seq(0,1,0.01)

df <- expand.grid(x = x, loci = loci)
df <- df %>% mutate(y = loci * x)

cols = c("red", "blue", "green")

for (i in loci){
  
  plot_this <- df %>% filter(loci == i)
  
  my_plot = ggplot(plot_this) +
    geom_point( aes( x = x, y = y/i), colour = cols[i]) +
    ylim(0,3) + ggtitle(paste0("i = ", i))
  
  assign(paste0("plot_", i), my_plot)
  print(plot_1)
}

grid.arrange(plot_1, plot_2, plot_3, ncol = 3)

Solution

  • It's due to the lazy evaluation nature of ggplot, and more explanation can be found in this post.

    "Looping" with lapply avoids the problem.

    Data

    library(ggplot2)
    library(gridExtra)
    library(dplyr)
    
    loci = c(1,2,3)
    x <- seq(0,1,0.01)
    
    df <- expand.grid(x = x, loci = loci)
    df <- df %>% mutate(y = loci * x)
    
    cols = c("red", "blue", "green")
    

    Code

    my_plot <- lapply(loci, function(i) {
      df %>% 
        filter(loci == i) %>% 
        ggplot() + 
        geom_point(aes(x = x, y = y/i), colour = cols[i]) + 
        ylim(0,3) + 
        ggtitle(paste0("i = ", i))
      })
    
    grid.arrange(my_plot[[1]], my_plot[[2]], my_plot[[3]], ncol = 3)
    

    Created on 2022-04-26 by the reprex package (v2.0.1)