Как мне создать "макрос" для регрессоров в R?
Для длинных и повторяющихся моделей я хочу создать "макрос" (так называемый в Stata и там выполняется с global var1 var2 ...
), который содержит регрессоры модельной формулы.
Например из
library(car)
lm(income ~ education + prestige, data = Duncan)
Я хочу что-то вроде:
regressors <- c("education", "prestige")
lm(income ~ @regressors, data = Duncan)
Я мог бы найти этот подход. Но моя заявка на регрессоры не будет работать:
reg = lm(income ~ bquote(y ~ .(regressors)), data = Duncan)
как это меня кидает
Error in model.frame.default(formula = y ~ bquote(.y ~ (regressors)), data =
Duncan, : invalid type (language) for variable 'bquote(.y ~ (regressors))'
Даже принятый ответ на тот же вопрос:
lm(formula(paste('var ~ ', regressors)), data = Duncan)
поражает и показывает мне:
Error in model.frame.default(formula = formula(paste("var ~ ", regressors)),
: object is not a matrix`.
И конечно же я попробовал as.matrix(regressors)
:)
Итак, что еще я могу сделать?
2 ответа
Вот несколько альтернатив. Пакеты не используются в первых 3.
1) переформулировать
fo <- reformulate(regressors, response = "income")
lm(fo, Duncan)
или, возможно, вы захотите написать последнюю строку, как эта, чтобы формула, показанная в выводе, выглядела лучше
do.call("lm", list(fo, quote(Duncan)))
в этом случае строка Call: выводится, как и ожидалось, а именно:
Call:
lm(formula = income ~ education + prestige, data = Duncan)
2) лм (датафрейм)
lm( Duncan[c("income", regressors)] )
Вызов Call: строка выглядит следующим образом:
Call:
lm(formula = Duncan[c("income", regressors)])
но мы можем заставить его выглядеть точно так же, как в do.call
решение в (1) с этим кодом:
fo <- formula(model.frame(income ~., Duncan[c("income", regressors)]))
do.call("lm", list(fo, quote(Duncan)))
3) точка
Альтернатива, аналогичная предложенной @jenesaisquoi в комментариях:
lm(income ~., Duncan[c("income", regressors)])
Подход, обсуждаемый в (2) к Call: output, также работает здесь.
4) fn$ Предопределение функции с помощью fn$ включает интерполяцию строк в ее аргументах. Это решение почти идентично желаемому синтаксису, показанному в вопросе, использующему $ вместо @ для выполнения подстановки, и гибкая подстановка может легко распространяться на более сложные сценарии. quote(Duncan)
в коде может быть написано просто Duncan
и он все еще будет работать, но вызов: показано в lm
вывод будет выглядеть лучше, если вы используете quote(Duncan)
,
library(gsubfn)
rhs <- paste(regressors, collapse = "+")
fn$lm("income ~ $rhs", quote(Duncan))
Линия Call: выглядит практически идентично do.call
Решения выше - отличаются только пробел и кавычки:
Call:
lm(formula = "income ~ education+prestige", data = Duncan)
Если вы хотели абсолютно то же самое, тогда:
fo <- fn$formula("income ~ $rhs")
do.call("lm", list(fo, quote(Duncan)))
Для сценария, который вы описали, где regressors
находится в глобальной среде, вы можете использовать:
lm(as.formula(paste("income~", paste(regressors, collapse="+"))), data =
Duncan)
В качестве альтернативы вы можете использовать функцию:
modincome <- function(regressors){
lm(as.formula(paste("income~", paste(regressors, collapse="+"))), data =
Duncan)
}
modincome(c("education", "prestige"))