使用R的lm(),公式对象应该作为字符传递?

时间:2015-12-24 11:50:45

标签: r lm

我发现了一个使用lm()的R的奇怪行为。

基于cars对象,以下函数用于绘制拟合的断裂距离,并以30的速度进行局部线性回归。

func1 <- function(fm, spd){
  w <- dnorm(cars$speed - spd, sd=5)
  fit <- lm(formula = as.formula(fm), weights = w, data=cars)
  plot(fitted(fit))
}

func2 <- function(fm, spd){
  w <- dnorm(cars$speed - spd, sd=5)
  fit <- lm(formula = fm, weights = w, data=cars)
  plot(fitted(fit))
}

func1("dist ~ speed", 30)
func2(dist ~ speed, 30)

func1有效。但func2失败并显示以下消息:

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

两个函数之间的唯一区别是func2接收公式类作为参数。

在这种风格中使用R的lm(),公式对象应该作为字符传递?

我用R-3.2.1,RStudio 0.99.467,Windows7测试了这个。

1 个答案:

答案 0 :(得分:2)

非常有趣的案例!这与R的环境特征有很大关系。 简而言之,似乎我们不应该将外部定义的公式对象传递给函数。虽然有一些方法可以调整,但这种行为可能让我们感到惊讶。

?formula说:

  

公式对象具有关联环境,并且此环境(而不是父环境)由model.frame用于来评估在提供的数据参数中找不到的变量。

func1中,公式在函数内生成,因此它与函数环境相关联(函数形成一个环境)。 因此,当data中找不到对象时,lm调用会在函数环境中查找它们。这就是w中找到func1的方式。

在第二个示例中,公式在函数外部定义,或者更确切地说,在全局环境中定义。因此,如果在data中找不到,则公式会查找全局中的对象。由于全局中没有w,因此失败。更糟糕的是,如果全局中有另一个w,则w会被混淆并用作权重。

这是一个突出显示对象搜索顺序的示例。 数据只有y。因此,lm调用会在其他位置查找x。 但有两个xfm,在全局搜索x = 1:10中定义的公式,而在函数中定义的as.formula(ch)找到x = 10:1environment告诉您公式与哪个环境相关联。

fun <- function(fm, ch) {
  x <- 10:1
  dat <- data.frame(y = 1:10)

  print(environment(fm))
  print(lm(fm, data = dat))
  cat("<--- refers to x in the global\n") 

  print(environment(as.formula(ch)))
  print(lm(as.formula(ch), data = dat))
  cat("<--- refers to x in the function\n\n")
}

x <- c(1:10)
fun(y ~ x, "y ~ x")

另请参阅:Environments - Advanced R