在aes内的局部变量

时间:2012-05-18 20:15:48

标签: r ggplot2

当我用ggplot绘图时,我正试图在aes中使用局部变量。这是我的问题归结为本质:

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)

这会导致以下错误:

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

好像我不能在aes中使用局部变量(或函数参数)。当局部变量超出范围时,由于aes的内容后来执行会不会发生?如何避免此问题(除了不使用aes中的局部变量)?

6 个答案:

答案 0 :(得分:37)

我会捕捉当地的环境,

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)

答案 1 :(得分:10)

这是一个替代方案,允许您通过YMul参数传递任何值,而无需将其添加到Data data.frame或全局环境中:

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)

要了解其工作原理,请单独尝试以下行:

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

答案 2 :(得分:5)

ggplot()的{​​{1}}期望aes成为YMul数据框内的变量。请尝试在其中包含data

感谢@Justin:YMull的{​​{1}}似乎首先在ggplot()数据框中查找aes,如果没有找到,那么在全球环境中。我喜欢将这些变量添加到数据框中,如下所示,因为它在概念上对我有意义。我也不必担心全局变量的变化会对功能产生意想不到的后果。但所有其他答案也是正确的。所以,请使用适合你的。

YMul

或者,如果您想要示例中的函数:

data

答案 3 :(得分:4)

我正在使用ggplot2,您的示例似乎可以正常使用当前版本。

然而,很容易想出仍然会造成麻烦的变种。我自己也被类似的行为所困惑,这就是我发现这篇文章的方式(谷歌的最佳结果是“ggplot如何在传递时评估变量”)。例如,如果我们将ggplot移出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

在上面的变体中,“捕获本地环境”不是解决方案,因为没有从函数内部调用ggplot,只有ggplot具有“environment =”参数。

但现在有一系列函数“aes_”,“aes_string”,“aes_q”,它们类似于“aes”但捕获局部变量。如果我们在上面使用“aes_”,我们仍然会收到错误,因为它现在不知道“x”。但很容易直接引用数据,这解决了问题:

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

答案 4 :(得分:1)

您是否看过@wch(W。Chang)给出的解决方案?

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

我认为这是更好的一个

基本上类似于@baptiste,但在调用ggplot时直接包含对环境的引用

我在这里报告

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

g()
# Works

答案 5 :(得分:0)

如果您在函数之外执行代码,它就可以运行。如果你在全局定义YMul的函数中执行代码,它就可以工作。我不完全理解ggplot的内部运作,但这有效......

YMul <- 2

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

plotfunc(xy)