1

If i pass a value to ggplot, it is stored as a reference so if it gets modified, the plot is changed as well. However, this only happens if it is given to the aes function, not the geom_hline in my example.

library(ggplot2)

# The line is at 10
value <- 10
pl <- ggplot() + geom_hline(yintercept=value)
value <- 0
pl

# The line is at 0
value <- 10
pl <- ggplot() + geom_hline(aes(yintercept=value))
value <- 0
pl

I believe this question is related to this one, but I don't understand what I can do to avoid this behaviour. Can I force ggplot to make a copy of the data?

Regarding the use case, imagine I have a loop to plot many separate figures and value changes at each iteration of the loop.

plot_list <- NULL
for (value in 1:10) {
  # The title goes from 1 to 10 but all the lines are on 10.
  plot_list[[value]] <- ggplot() + geom_hline(aes(yintercept=value)) + labs(title=value)
}
plot_list
wohlrajh
  • 139
  • 1
  • 8
  • 1
    It’s a lazy evaluation problem. The plots are only created at the end of the loop, when `value` is `10`. The easiest solution is to switch the `fir` loop to `lapply`. – Limey Aug 12 '22 at 09:56

1 Answers1

1

I think this is because your plot list is not really saving the object of the plot, but rather the code for the plot. I don't know exactly how to change that behavior, but your desired behavior is achieved quite easily with a map function.

First, make the plotting function, with value as input:

plotter <- function(value) {
  
  new_plot <- 
    ggplot() +
    geom_hline(aes(yintercept = value))
  
  return(new_plot)
  
}

Map the function over your list of values, 1:10:

my_plots <- map(.x = 1:10, .f = plotter)

Now you can see that the ggplot objects in your saved list are updated appropriately:

my_plots[[1]]
my_plots[[5]]

I find map functions much more helpful and intuitive than looping in most cases, so I hope this helps!

Jamie
  • 401
  • 3
  • 11