monte
monte

Reputation: 1885

Plots using loop

Hi I am trying to create plots, using a for loop and assigning them in my global envirnoment, as follows:

library(ggplot2)
library(patchwork)

datasets::anscombe
#>    x1 x2 x3 x4    y1   y2    y3    y4
#> 1  10 10 10  8  8.04 9.14  7.46  6.58
#> 2   8  8  8  8  6.95 8.14  6.77  5.76
#> 3  13 13 13  8  7.58 8.74 12.74  7.71
#> 4   9  9  9  8  8.81 8.77  7.11  8.84
#> 5  11 11 11  8  8.33 9.26  7.81  8.47
#> 6  14 14 14  8  9.96 8.10  8.84  7.04
#> 7   6  6  6  8  7.24 6.13  6.08  5.25
#> 8   4  4  4 19  4.26 3.10  5.39 12.50
#> 9  12 12 12  8 10.84 9.13  8.15  5.56
#> 10  7  7  7  8  4.82 7.26  6.42  7.91
#> 11  5  5  5  8  5.68 4.74  5.73  6.89


for(i in 1:4){
  var = paste0('p', as.character(i))
  assign(
    x = var,
    value = (ggplot(anscombe, 
                   aes(x=get(paste0('x', as.character(i))), 
                       y=get(paste0('y', as.character(i))))) + geom_point()),
    envir=.GlobalEnv
  )
}

(p1 + p2)/(p3 + p4)

As you can see, all the plots produced are same. But when I use the above same code without for loops, I get intended plots for example: p1 and p3 are shown below.


p1 = ggplot(anscombe, aes(x=get(paste0('x', as.character(1))),
                          y=get(paste0('y', as.character(1))))) + geom_point() 

p3 = ggplot(anscombe, aes(x=get(paste0('x', as.character(3))),
                     y=get(paste0('y', as.character(3))))) + geom_point() 
p1 + p3

Created on 2020-09-06 by the reprex package (v0.3.0)

My question is why isn't the for loop working? Why it's producing the p4 plot for all in the for loop?

Upvotes: 1

Views: 125

Answers (1)

Allan Cameron
Allan Cameron

Reputation: 174478

You could make this a bit simpler by creating column names and passing them to ggplot, then selectively unquoting them with !!

Note that you're already in the global environment so assign doesn't need the envir argument.

for(i in 1:4) {
  var = paste0('p', i)
  x <- as.name(paste0("x", i))
  y <- as.name(paste0("y", i))
  assign(x = var, value = ggplot(anscombe, aes(!!x, !!y)) + geom_point())
}

(p1 + p2)/(p3 + p4)

enter image description here

Incidentally, you could be even more succinct and avoid writing multiple objects to the global environment if you kept all the plots in a list:

p <- lapply(1:4, function(i) {
  ggplot(anscombe, aes(!!as.name(paste0("x", i)), !!as.name(paste0("y", i)))) + 
    geom_point()
})

(p[[1]] + p[[2]])/(p[[3]] + p[[4]])

Upvotes: 1

Related Questions