为什么as.formula只能在lm()里面用()?

时间:2014-09-04 07:21:15

标签: r formula with-statement environments

使用R,这是一个真正的WTF:

R> f_string <- 'Sepal.Length ~ Sepal.Width'
R> l <- with(iris, lm(as.formula(f_string))) # works fine

R> f_formula <- as.formula(f_string)
R> l <- with(iris, lm(f_formula))
Error in eval(expr, envir, enclos) : object 'Sepal.Length' not found

为什么as.formula必须在lm()电话中?我知道这是一个关于评估哪些环境的问题,因为这有效:

R> f_formula <- with(iris, as.formula(f_string))
R> lm(f_formula)

但是我很难绕过为什么一个人工作而另一个人不工作。

1 个答案:

答案 0 :(得分:2)

您失败的示例失败,因为您正在使用全局环境创建公式:

> f_formula <- as.formula(f_string)
> l <- with(iris, lm(f_formula))
Error in eval(expr, envir, enclos) : object 'Sepal.Length' not found
> str(f_formula)
Class 'formula' length 3 Sepal.Length ~ Sepal.Width
  ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 

那里没有Sepal.Length。如果在全局环境中创建适当的对象,则可以使其工作:

> Sepal.Length=1:10
> Sepal.Width=runif(10)
> l <- with(iris, lm(f_formula)) # "works" (ie doesn't error)

但那是完全忽略 iris数据。欢迎来到恼人的R行为世界。

其他示例都是将iris数据框中的公式对象计算为环境。如果您调试lm并查看其中一个工作案例中formula的内容:

Browse[2]> str(formula)
Class 'formula' length 3 Sepal.Length ~ Sepal.Width
  ..- attr(*, ".Environment")=<environment: 0x9d590b4> 

你会发现环境不再是全球环境。如果您想查看该环境中的内容,请从公式的属性和列表中获取它:

Browse[2]> e = attr(formula,".Environment")
Browse[2]> with(e,ls())
[1] "Petal.Length" "Petal.Width"  "Sepal.Length" "Sepal.Width"  "Species"