Enriching a ggplot2 plot with multiple geom_segment in a loop?

10,112

Solution 1

It has to do with the lazy evaluation of the aes() values. You are binding to the variable i but not actually doing anything with it in the loop. The mappings aren't resolved till you actually print(p). Essentially this means they are all being bound to i and after the loop exits, i will have the value it had during the final loop.

So the problem really is you shounld't be using aes() here as you don't really want active binding. Just set the x and xend values outside the aes(). (And since the y's are constant they should be outside the aes() as well).

values <- c(1, 5)
for (i in values) {
   p <- p + geom_segment(x=i, y=103, xend=i, yend=107)
}

Solution 2

An alternative approach would be to avoid using a loop at all. You can pack your segment data up in a separate data.frame from your main data and use aes() to plot everything at once like so:

segment_data = data.frame(
    x = c(1, 5),
    xend = c(1, 5), 
    y = c(103, 103),
    yend = c(107, 107)
)

p = ggplot(df, ...) +
geom_segment(data = segment_data, aes(x = x, y = y, xend = xend, yend = yend))
Share:
10,112
SkyWalker
Author by

SkyWalker

How would you be rated on a technical skill that you haven't used yet e.g. tableau? Check out my Stack Overflow skill recommender system: https://github.com/bravegag/HarvardX-Skillability

Updated on June 23, 2022

Comments

  • SkyWalker
    SkyWalker almost 2 years

    I successfully create a plot using the following:

    # suppose I have a p <- ggplot(data=df, ...) then the following works 
    # I get those two segments plotted correctly
    p <- p + geom_segment(aes(x=1,y=103,xend=1,yend=107))
    p <- p + geom_segment(aes(x=5,y=103,xend=5,yend=107))
    

    However if I do:

    values <- c(1, 5)
    for (i in values) {
       p <- p + geom_segment(aes(x=i,y=103,xend=i,yend=107))
    }
    

    It doesn't work, only the last segment is created. Can anyone advice what's wrong here?

  • MrFlick
    MrFlick almost 10 years
    What i posted will fix it. Don't use aes() in the geom_segment() in the loop.
  • csgillespie
    csgillespie almost 10 years
    That's what I thought. Do you know why adding a print statement or using force in the for loop doesn't fix the problem?
  • MrFlick
    MrFlick almost 10 years
    @csgillespie Because in this case you're still binding to the variable i, not the value. You can't force aes to resolve the name till it actually draws the plot. force is sometimes useful in situations like this, but with the non-standard evaluation of aes it won't help in this case.
  • aaiezza
    aaiezza almost 7 years
    This does seem better. I can't even get the other answer to work!
  • Taylor White
    Taylor White over 5 years
    @SkyWalker can you make this the answer?