aes中的局部variables
我试图在aes
使用局部variables时,我与ggplot的情节。 这是我的问题归结为本质:
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
使用局部variables(或函数参数)。 难道是由于aes
的内容在局部variables超出范围的时候被执行了吗? 我怎样才能避免这个问题(除了不使用aes
内的局部variables)?
我会捕捉当地的环境,
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)
下面是一个替代scheme,允许您通过YMul
parameter passing任何值,而不必将其添加到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))
ggplot()
的aes
预计YMul
是data
数据框架内的一个variables。尝试包括 YMull
:
感谢@Justin: ggplot()
的aes
似乎YMul
在data
数据框架中查找YMul
,如果找不到,那么在全局环境中。 我喜欢在数据框中添加这样的variables,如下所示,因为这对我来说在概念上是有意义的。 我也不必担心全局variables对函数有意想不到的后果。 但所有其他答案也是正确的。 所以,select适合你的。
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()
或者,如果你想在你的例子中的function:
plotfunc <- function(Data, YMul = 2) { ggplot(cbind(Data, YMul), aes(x = x, y = y * YMul)) + geom_line() } plotfunc(xy)
我正在使用ggplot2,你的例子似乎与当前版本正常工作。
但是,很容易想出一些仍然会造成麻烦的变种。 我被我自己困惑的类似的行为,这就是我发现这个职位(顶部谷歌结果“ggplot如何评估variables时通过”)。 例如,如果我们将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
在上面的变种中,“捕获本地环境”不是一个解决scheme,因为ggplot不是从函数内部调用的,只有ggplot有“environment =”参数。
但现在有一系列函数“aes_”,“aes_string”,“aes_q”,它们就像“aes”,但捕获局部variables。 如果我们在上面使用“aes_”,我们仍然得到一个错误,因为现在它不知道“x”。 但是直接引用数据很容易,解决了这个问题:
plotfunc <- function(Data,YMul=2){ geom_line(aes_(x=Data$x,y=Data$y*YMul)) } ggplot(xy)+plotfunc(xy) # works
你看过@wch(W. Chang)给出的解决scheme吗?
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
如果你在它的函数之外执行你的代码。 如果你在全局定义的YMul
函数内执行代码,它就可以工作。 我不完全了解ggplot
的内部工作,但这个工程…
YMul <- 2 plotfunc <- function(Data){ ggplot(Data,aes(x=x,y=y*YMul))+geom_line() } plotfunc(xy)