R函数:函数内部的奇怪行为

时间:2015-11-15 08:54:29

标签: r

在将函数放入函数中时,我会遇到奇怪的行为(使用带有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)

1 个答案:

答案 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中的其他图形包不同。