R - 如何将公式传递给 with(data, lm(y ~ x)) 结构

R - how to pass a formula to a with(data, lm(y ~ x)) construction

此问题与 高度相关,但提出了更广泛的问题。

为什么这些表达式有效?

text_obj <- "mpg ~ cyl"
form_obj <- as.formula(text_obj)

with(mtcars, lm(mpg ~ cyl)) 
with(mtcars, lm(as.formula(text_obj))) 
lm(form_obj, data = mtcars)

但不是这个?

with(mtcars, lm(form_obj))
Error in eval(predvars, data, env) : object 'mpg' not found

我通常会使用 data 参数,但这在 mice 包中是不可能的。 IE。

library(mice)
mtcars[5, 5] <- NA # introduce a missing value to be imputed
mtcars.imp = mice(mtcars, m = 5)

这些都不行

lm(form_obj, data = mtcars.imp)
with(mtcars.imp, lm(form.obj))

但这确实

with(mtcars.imp, lm(as.formula(text_obj)))

因此,总是这样在函数内部使用 as.formula 参数,而不是先构造它然后传入它更好吗?

公式的一个重要“隐藏”方面是它们的关联环境。

创建 form_obj 时,其环境设置为创建 form_obj 的环境:

environment(form_obj)
# <environment: R_GlobalEnv>

对于每个其他版本,公式的环境是从 with() 中创建的,并设置为该临时环境。通过将 as.formula 方法分成几个步骤,最容易看出这一点:

with(mtcars, {
  f = as.formula(text_obj)
  print(environment(f))
  lm(f)
})
# <environment: 0x7fbb68b08588>

我们可以通过在调用 lm:

之前编辑其环境来使 form_obj 方法起作用
with(mtcars, {
  # set form_obj's environment to the current one
  environment(form_obj) = environment()
  lm(form_obj)
})

?formula 的帮助页面有点长,但是有一个关于环境的部分:

Environments

A formula object has an associated environment, and this environment (rather than the parent environment) is used by model.frame to evaluate variables that are not found in the supplied data argument.

Formulas created with the ~ operator use the environment in which they were created. Formulas created with as.formula will use the env argument for their environment.

结果是,使用 ~ 制作公式会将环境部分“隐藏起来”——在更一般的设置中,使用 as.formula 更安全,它可以让您更全面地控制公式适用的环境。

您还可以查看 Hadley 关于环境的章节:

http://adv-r.had.co.nz/Environments.html