R - как передать формулу в конструкцию with (data, lm (y ~ x)) - PullRequest
0 голосов
/ 13 января 2020

Этот вопрос тесно связан с R - как передать формулу в конструкцию with (df, glm (y ~ x)) внутри функции , но задает более широкий вопрос.

Почему эти выражения работают?

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 внутри функции, а не создавать ее сначала, а затем передать в?

1 Ответ

3 голосов
/ 13 января 2020

Важным «скрытым» аспектом формул является связанная с ними среда.

Когда создается 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>

Мы можем заставить подход form_obj работать, отредактировав его среду перед вызовом lm:

with(mtcars, {
  # set form_obj's environment to the current one
  environment(form_obj) = environment()
  lm(form_obj)
})

Страница справки для ?formula немного длинная, но есть раздел о средах:

Среды

У объекта формулы есть связанная среда, и эта среда (а не родительская среда) используется model.frame для оценки переменных, которые не найдены в предоставленном аргументе данных.

Формулы, созданные с помощью оператора ~, используют среду, в которой они были созданы , Формулы, созданные с помощью as.formula, будут использовать аргумент env для своей среды.

В результате, если формула с ~ помещает часть среды "под ковер" - в более общие настройки, безопаснее использовать as.formula, что дает вам более полный контроль над средой, к которой применяется формула.

Вы также можете проверить главу Хэдли о средах:

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

...