Как мне создать "макрос" для регрессоров в 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"))
Другие вопросы по тегам