studio - Variables locales dentro de aes
ggplot2 tutorial (6)
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 alcance? ¿Cómo puedo evitar este problema (aparte de no usar la variable local dentro de aes
)?
¿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
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))
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)
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
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)
ggplot()
espera que YMul
sea una variable dentro del marco de datos.Intenta incluir YMull
allí en su lugar:
Gracias a @Justin: ggplot()
parece buscar YMul
en el marco de datos y, si no se encuentra, en el entorno global. Me gusta agregar tales variables al marco de datos, 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)