为什么as.formula只在lm()和()中起作用?
与R合作,这是一个真正的WTF:为什么as.formula只在lm()和()中起作用?,r,formula,with-statement,environments,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)
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
但是我真的很难理解为什么一个有效而另一个无效。你失败的例子失败了,因为你是在全球环境中创建公式的:
> 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>
但这完全忽略了iris
数据。欢迎来到令人讨厌的行为世界
其他示例都是将iris
数据帧中的公式对象作为环境进行计算。如果调试lm
并查看其中一个工作案例中的公式是什么:
Browse[2]> str(formula)
Class 'formula' length 3 Sepal.Length ~ Sepal.Width
..- attr(*, ".Environment")=<environment: 0x9d590b4>
您可能希望清理代码并使其完全可复制。然而,把的代码看作.formula,我也不明白。我原以为as.formula(f_string,env=basenev())
或as.formula(f_string,env=parent.frame())
应该可以工作(我希望是前者),但前提是env
缺少它才能工作。(我希望你知道你不应该在这里使用。lm
和朋友有一个data
的争论是有原因的。)@Roland呜呜,不小心在里面留下了一些碎片……@Roland:data=
的争论也是完全正确的。它可以让lm()
很好地处理字符串,因此我可以避免整个问题。不过,作为compsci新手,使用environment()
还是有意思的:在我看来,与attr(x,.environment”)
相比,使用environment()
是一种稍微漂亮一点的方式来获取分配给对象的环境。因此,您可以执行类似于ls(envir=environment(f_公式))
的操作。我几乎不会称这种行为为“恼人的”,因为这意味着可以轻松地处理lm()
的data=
参数。当你不正确地使用函数时,不要对它们发火。正如@Roland首先说的,使用lm(f_公式,iris)
而不是with(iris,lm(f_公式))
。我使用了这个符号,因为str(f)
就是这样显示的。大多数R对象(函数、数据帧)不将其环境存储在属性中。我不知道为什么<代码>打印。公式
很有趣。令人烦恼的是,对于一种函数式语言,在公式中会有一些纯粹的函数主义者会回避的评估问题。
> Sepal.Length=1:10
> Sepal.Width=runif(10)
> l <- with(iris, lm(f_formula)) # "works" (ie doesn't error)
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"