Variables locales dentro de aes

Estoy tratando de usar una variable local en aes cuando trazo con ggplot. Este es mi problema reducido a la esencia:

 xy <- data.frame(x=1:10,y=1:10) plotfunc <- function(Data,YMul=2){ ggplot(Data,aes(x=x,y=y*YMul))+geom_line() } plotfunc(xy) 

Esto produce el siguiente error:

 Error in eval(expr, envir, enclos) : object 'YMul' not found 

Parece que no puedo usar variables locales (o argumentos de funciones) en aes . ¿Podría ser que ocurriera debido a que el contenido de aes se ejecuta más adelante cuando la variable local está fuera del scope? ¿Cómo puedo evitar este problema (aparte de no usar la variable local dentro de aes )?

Capturaría el entorno local,

 xy <- data.frame(x=1:10,y=1:10) plotfunc <- function(Data, YMul = 2){ .e <- environment() ggplot(Data, aes(x = x, y = y*YMul), environment = .e) + geom_line() } plotfunc(xy) 

Aquí hay una alternativa que le permite pasar cualquier valor a través del argumento de YMul sin tener que agregarlo a Data data.frame o al entorno global:

 plotfunc <- function(Data, YMul = 2){ eval(substitute( expr = { ggplot(Data,aes(x=x,y=y*YMul)) + geom_line() }, env = list(YMul=YMul))) } plotfunc(xy, YMul=100) 

Para ver cómo funciona esto, prueba la siguiente línea de forma aislada:

 substitute({ggplot(Data, aes(x=x, y=y*YMul))}, list(YMul=100)) 

ggplot() espera que YMul sea ​​una variable dentro del dataframe. Intenta incluir YMull allí en su lugar:

Gracias a @Justin: ggplot() parece buscar YMul en el dataframe y, si no se encuentra, en el entorno global. Me gusta agregar tales variables al dataframe, de la siguiente manera, ya que tiene sentido para mí conceptualmente. Tampoco tengo que preocuparme por los cambios en las variables globales que tienen consecuencias inesperadas para las funciones. Pero todas las demás respuestas también son correctas. Por lo tanto, use el que más le convenga.

 require("ggplot2") xy <- data.frame(x = 1:10, y = 1:10) xy <- cbind(xy, YMul = 2) ggplot(xy, aes(x = x, y = y * YMul)) + geom_line() 

O bien, si desea la función en su ejemplo:

 plotfunc <- function(Data, YMul = 2) { ggplot(cbind(Data, YMul), aes(x = x, y = y * YMul)) + geom_line() } plotfunc(xy) 

Estoy usando ggplot2, y su ejemplo parece funcionar bien con la versión actual.

Sin embargo, es fácil encontrar variantes que sigan creando problemas. Yo mismo estaba confundido por un comportamiento similar, y así es como encontré esta publicación (resultado superior de Google para “ggplot cómo evaluar variables cuando se pasa”). Por ejemplo, si movemos ggplot fuera de plotfunc:

 xy <- data.frame(x=1:10,y=1:10) plotfunc <- function(Data,YMul=2){ geom_line(aes(x=x,y=y*YMul)) } ggplot(xy)+plotfunc(xy) # Error in eval(expr, envir, enclos) : object 'YMul' not found 

En la variante anterior, "capturar el entorno local" no es una solución porque ggplot no se llama desde la función, y solo ggplot tiene el argumento "environment =".

Pero ahora hay una familia de funciones "aes_", "aes_string", "aes_q" que son como "aes" pero capturan variables locales. Si utilizamos "aes_" en el cuadro anterior, aún recibimos un error porque ahora no se conoce acerca de "x". Pero es fácil referirse a los datos directamente, lo que resuelve el problema:

 plotfunc <- function(Data,YMul=2){ geom_line(aes_(x=Data$x,y=Data$y*YMul)) } ggplot(xy)+plotfunc(xy) # works 

¿Has mirado la solución dada por @wch (W. Chang)?

https://github.com/hadley/ggplot2/issues/743

Creo que es el mejor

esencialmente es como el de @baptiste pero incluye la referencia al entorno directamente en la llamada a ggplot

Lo reporto aquí

 g <- function() { foo3 <- 4 ggplot(mtcars, aes(x = wt + foo3, y = mpg), environment = environment()) + geom_point() } g() # Works 

Si ejecuta su código fuera de la función, funciona. Y si ejecuta el código dentro de la función con YMul definido globalmente, funciona. No entiendo completamente el funcionamiento interno de ggplot pero esto funciona …

 YMul <- 2 plotfunc <- function(Data){ ggplot(Data,aes(x=x,y=y*YMul))+geom_line() } plotfunc(xy)