Let\'s assume we have the following data frame
data <- data.frame(time=1:10, y1=runif(10), y2=runif(10), y3=runif(10))
and we want to create
NOTE: This is not really an answer, just a very partial explanation of what is going on behind the scenes that might set on you on the right track. I have to admit my understanding of NSE is still very basic.
I have struggled and am still struggling with this particular issue. I have narrowed down the issue to NSE. I am not familiar with R's native substitute/quote/eval stuff, so I am going to demonstrate using the lazyeval
package.
library(lazyeval)
a <- lapply(c(1:9,13), function(i) lazy(i))
head(a)
# [[1]]
#
# expr: c(1, 2, 3, 4, 5, 6, 7, 8, 9, 13)[[10L]]
# env:
#
# [[2]]
#
# expr: c(1, 2, 3, 4, 5, 6, 7, 8, 9, 13)[[10L]]
# env:
#
# ...........
lazy_eval(a[[1]])
# [1] 13
lazy_eval(a[[2]])
# [1] 13
I think this happens because lazy(i)
binds to the promise of i
. By the time we get to evaluating any of these i
evaluations, i
is whatever was LAST assigned to it -- in this case, 13
. Perhaps this is due to the environment in which i
is evaluated being shared over all iterations of the lapply
function?
I have had to resort to the same workarounds as you through aes_string
and aes_q
. I found them quite unsatisfactory as they neither (1) fully consistent with aes
behavior and (2) particularly clean. Oh, the joys of learning NSE ;)
You can find the source code of the +
and aes
operators here:
ggplot2:::`+.gg`
ggplot2:::aes
ggplot2:::aes_q
ggplot2:::aes_string