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

2024-03-10

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

基于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 对此进行了测试。


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

?formula says:

公式对象有一个相关环境, and 这个环境(而不是父环境)is used通过 model.frame 来评估在提供的数据参数中找不到的变量。

In your func1,公式是在函数内部生成的,因此它与函数环境相关联(函数形成环境)。 因此,当没有找到对象时data, the lmcall 在函数环境中查找它们。就是那样w发现于func1.

在第二个示例中,公式是在函数外部定义的,或者更准确地说,是在全局环境中定义的。因此,如果在全局中找不到对象,则该公式会在全局中查找对象data。既然没有w在全球范围内,它失败了。更糟糕的是,如果你有另一个w在全球范围内,这w会被混淆并用作权重。

这是一个突出显示对象搜索顺序的示例。 数据只有y。因此lm呼叫寻找x别处。 但有两个x. fm,全局查找中定义的公式x = 1:10, while as.formula(ch),在函数中定义,找到x = 10:1. environment告诉您公式与哪个环境相关联。

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")

也可以看看:环境 - 高级 R http://adv-r.had.co.nz/Environments.html.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐