当我用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
中的局部变量)?
答案 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)