rlistfor-loopggplot2geom-segment

geom_segment() doesn't store object value defined inside a for loop


I defined a very simple for loop in which I plot a normal distribution with a vertical red line and a smaller vertical black segment. The normal distribution doesn't change, but the position of the vertical line and the vertical segment are supposed to change at each iteration.
If a plot the ggplot() objects on the fly after every iteration, the lines are correctly displayed, but if I store each plot in a list and then I plot the list, the vertical black segment has always the value defined in the last loop. Please check the reprex below:

set.seed(seed = 314159)

library(ggplot2)

plots_list <- list()

for (number in c(1:10)) {

  line <- number
  segment <- number + 1

  p <- ggplot(data = data.frame(x = c(-3, 3)),
              aes(x)) +
    stat_function(fun = dnorm,
                  n = 101,
                  args = list(mean = 0,
                              sd = 1)) +
    geom_vline(xintercept = line,
               colour = "red",
               size = 0.5,
               linetype = "dashed") +
    geom_segment(aes(x = segment,
                     xend = segment,
                     y = 0,
                     yend = 0.5),
                 linetype = "dashed")

  plot(p)

  plots_list[[number]] <- p

}

plots_list

If you check the plots after launching the plot_list object, you'll see the the red line changes position for each plot, while the black segment doesn't. Any suggestion about how to solve that? Thanks!


Solution

  • You have to take out aes().

    The original geom_segment() call is in blue. The commented out code for annotate() works the same as geom_segment() without aes().

    set.seed(seed = 314159)
    
    library(ggplot2)
    
    plots_list <- list()
    
    for (number in c(1:10)) {
      line <- number
      segment <- number + 1
      
      p <- ggplot(data = data.frame(x = c(-3, 3)),
                  aes(x)) +
        stat_function(fun = dnorm,
                      n = 101,
                      args = list(mean = 0,
                                  sd = 1)) +
        geom_vline(xintercept = line,
                   colour = "red",
                   size = 0.5,
                   linetype = "dashed") +
        geom_segment(x = segment,           # the new segment is black
                     xend = segment,
                     y = 0,
                     yend = 0.5,
                     linetype = "dashed") +
        geom_segment(aes(x = segment,       # your original segment is blue
                         xend = segment,
                         y = 0,
                         yend = 0.5),
                     linetype = "dashed",
                     col = "blue")
        # annotate("segment",        # this works, too
        #          x = segment,
        #          xend = segment,
        #          y = 0,
        #          yend = 0.5,
        #          linetype = "dashed",
        #          col = "orange")
      
      plot(p)
      
      plots_list[[number]] <- p
    }
    
    plots_list
    

    enter image description here