J'essaie d'utiliser une variable locale dans aes
lorsque je trace avec ggplot. C'est mon problème qui se résume à l'essentiel:
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)
Cela entraîne l'erreur suivante:
Error in eval(expr, envir, enclos) : object 'YMul' not found
Il semble que je ne puisse pas utiliser de variables locales (ni d'arguments de fonction) dans aes
. Se pourrait-il que cela se produise à cause du contenu de aes
exécuté ultérieurement lorsque la variable locale est hors de portée? Comment puis-je éviter ce problème (autre que de ne pas utiliser la variable locale dans aes
)?
Je capturerais l'environnement 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)
Voici une alternative qui vous permet de transmettre n'importe quelle valeur à l'aide de l'argument YMul
sans avoir à l'ajouter à Data
data.frame ou à l'environnement 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)
Pour voir comment cela fonctionne, essayez la ligne suivante de manière isolée:
substitute({ggplot(Data, aes(x=x, y=y*YMul))}, list(YMul=100))
La aes
de ggplot()
s'attend à ce que YMul
soit une variable du cadre de données data
. Essayez d’y inclure YMull
:
Grâce à @Justin: la aes
de ggplot()
semble rechercher YMul
dans le bloc de données data
en premier, et si elle n’est pas trouvée, dans l’environnement global. J'aime ajouter de telles variables au bloc de données, comme suit, car cela me semble logique. De plus, je n'ai pas à m'inquiéter des changements apportés aux variables globales ayant des conséquences inattendues sur les fonctions. Mais toutes les autres réponses sont également correctes. Alors, utilisez celui qui vous convient le mieux.
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()
Ou, si vous voulez la fonction dans votre exemple:
plotfunc <- function(Data, YMul = 2)
{
ggplot(cbind(Data, YMul), aes(x = x, y = y * YMul)) + geom_line()
}
plotfunc(xy)
J'utilise ggplot2 et votre exemple semble bien fonctionner avec la version actuelle.
Cependant, il est facile de trouver des variantes qui créent encore des problèmes. J'étais moi-même décontenancé par un comportement similaire, et c'est la raison pour laquelle j'ai trouvé ce message (résultat Google supérieur pour "ggplot comment évaluer les variables une fois passées"). Par exemple, si nous déplaçons ggplot en dehors 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
Dans la variante ci-dessus, "capturer l'environnement local" n'est pas une solution car ggplot n'est pas appelé depuis la fonction, et seul ggplot a l'argument "environment =".
Mais il existe maintenant une famille de fonctions "aes_", "aes_string", "aes_q" qui ressemblent à "aes" mais capturent des variables locales. Si nous utilisons "aes_" dans ce qui précède, nous avons toujours une erreur car maintenant, il ne sait pas à propos de "x". Mais il est facile de se référer directement aux données, ce qui résout le problème:
plotfunc <- function(Data,YMul=2){
geom_line(aes_(x=Data$x,y=Data$y*YMul))
}
ggplot(xy)+plotfunc(xy)
# works
Avez-vous examiné la solution donnée par @wch (W. Chang)?
https://github.com/hadley/ggplot2/issues/743
Je pense que c'est le meilleur
est essentiellement comme celle de @baptiste mais incluez la référence à l'environnement directement dans l'appel à ggplot
Je le rapporte ici
g <- function() {
foo3 <- 4
ggplot(mtcars, aes(x = wt + foo3, y = mpg),
environment = environment()) +
geom_point()
}
g()
# Works
Si vous exécutez votre code en dehors de la fonction, cela fonctionne. Et si vous exécutez le code dans la fonction avec YMul
défini globalement, cela fonctionne. Je ne comprends pas bien le fonctionnement interne de ggplot
mais cela fonctionne ...
YMul <- 2
plotfunc <- function(Data){
ggplot(Data,aes(x=x,y=y*YMul))+geom_line()
}
plotfunc(xy)