在将函数放入函数中时,我会遇到奇怪的行为(使用带有R的' R Studio' 0.99.484的ggplot)。
我不明白为什么不能使用本地范围的变量来生成图。也许你可以启发我,并告诉我正确的方法。
这是一个重复我的麻烦的小代码片段:
# This works:
x1 <- seq(0,90,10)
ggplot() + geom_line(aes(x=x1,y=x1))
# This yields error below:
f1 <- function() {
x2 <- seq(0,90,10)
ret <- ggplot() + geom_line(aes(x=x2,y=x2))
return(ret)
}
f1()
Error in eval(expr, envir, enclos) : object 'x2' not found
# This fixes the error: but why myX needs to be global?
f1 <- function() {
myX <<- seq(0,90,10)
ret <- ggplot() + geom_line(aes(x=myX,y=myX))
return(ret)
}
f1()
# This yields error below:
f2 <- function(d) {
ret <- ggplot() + geom_line(aes(x=d,y=d))
return(ret)
}
f2(x1)
Error in eval(expr, envir, enclos) : object 'd' not found
# This fixes the error making all global: is this the right way to do it?
f2 <- function(d) {
myX <<- d
ret <- ggplot() + geom_line(aes(x=myX,y=myX))
return(ret)
}
f2(x1)
答案 0 :(得分:2)
在您的第一个示例中,问题是您在函数内声明了变量x2
,并且该变量是该函数的本地变量。这就是你得到错误的原因:找不到对象'x2'
如果要在函数外部使该变量可访问,可以使用运算符<<-
代替<-
,或使用函数assign
将其明确分配给全局环境。你可以在函数之外进行赋值。
# Option 1: <<-
f1 <- function() {
x2 <<- seq(0,90,10)
ret <- ggplot() + geom_line(aes(x=x2,y=x2))
return(ret)
}
f1()
# Option2: assign
f1 <- function() {
assign(x = "x2", value = seq(0,90,10), envir=.GlobalEnv)
ret <- ggplot() + geom_line(aes(x=x2,y=x2))
return(ret)
}
f1()
# Option 3: assignment outside the function
x2 <- seq(0,90,10)
f1 <- function() {
ret <- ggplot() + geom_line(aes(x=x2,y=x2))
return(ret)
}
f1()
扩大答案。原因是因为有bug in ggplot2:
aes()中的表达式在全局环境中进行评估,但它们都是如此 应该在调用环境中进行评估。
另一种解决方法是使用数据框(我们不应该使用向量)。因为aes
在传递给ggplot然后在全局环境中的数据框中首先出现。使用此代码,您将不会收到错误:
f1 <- function() {
x1 <- data.frame(x1 = seq(0,90,10))
ret <- ggplot(x1, aes(x = x1, y= x1)) + geom_line()
return(ret)
}
f1()
最后,重要的是要记住,在ggplot2中,数据必须是R数据帧。 Hadley Wickham在 ggplot2:数据分析的优雅图形中明确表示:
对数据的限制很简单:它必须是数据框。这个 是限制性的,与R中的其他图形包不同。