1

使用 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)

但是我很难理解为什么一个有效而另一个无效。

4

1 回答 1

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"     
于 2014-09-04T08:53:37.660 回答