3

I am having some problems updating a ggplot object. What I want to do is to put a vertical line in a specific location that I change on every loop, hence: multiple lines will be displayed in different locations. However, when I use a for loop it only shows me the last line that it's created but when I do it manually it works. I created a reproductible example that you guys can check:

library(ggplot2)

x <- ggplot(mapping = aes(x = 1:100, y = 1:100)) +
  geom_line()

for(i in 1:6){
  x <- x + geom_vline(aes(xintercept = i*5))
}

y <- ggplot(mapping = aes(x = 1:100, y = 1:100)) +
  geom_line()

y <- y + geom_vline(aes(xintercept = 5))
y <- y + geom_vline(aes(xintercept = 10))
y <- y + geom_vline(aes(xintercept = 15))
y <- y + geom_vline(aes(xintercept = 20))
y <- y + geom_vline(aes(xintercept = 25))
y <- y + geom_vline(aes(xintercept = 30))

Check both plots. Why is the first plot not looking the same as the second one, although for me both processes do the "same" thing?

Fustincho
  • 423
  • 2
  • 10
  • 2
    See [this answer](https://stackoverflow.com/a/39057372/496488) for an explanation of what's happening. – eipi10 Jun 01 '17 at 21:51
  • 1
    Using `aes_` instead of `aes` in the `geom_vline` for-loop will give you the same plot as y. – Adam Quek Jun 02 '17 at 02:49

2 Answers2

8

I was looking at some contributions that some people left me and there is one who solves it pretty efficiently and it is to use aes_() instead of aes(). The difference is that aes_() forces to evaluate and update the plot, while aes() only evaluates the indexes when the plot is drawn. Hence: it never updates while it is inside a for loop.

library(ggplot2)

x <- ggplot(mapping = aes(x = 1:100, y = 1:100)) +
  geom_line()

for(i in 1:6){
  x <- x + geom_vline(aes_(xintercept = i*5))
}
Fustincho
  • 423
  • 2
  • 10
  • 1
    This is a very simple solution to the problem with lazy evaluation in looping. – pep Jul 08 '21 at 22:13
0

It has to do with how ggplot does lazy evaluation -- see here.

Since geom_vline is vectorized, this works:

library(ggplot2)

x <- ggplot() +
  geom_line(mapping = aes(x = 1:100, y = 1:100))

x + geom_vline(aes(xintercept = seq(5,30,5)))
Alex Gold
  • 335
  • 1
  • 9
  • Thanks for the help, Alex. Actually, your example works in this reproductible example but it is quite limited in other applications. I was just reading some other comments that people let me and the best solution is to use aes_() instead of aes(). – Fustincho Jun 01 '17 at 22:15