如何在 R 中为回归量创建 "macro"?

How do I create a "macro" for regressors in R?

对于长而重复的模型,我想创建一个 "macro"(在 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) :)

那么,我还能做什么?

对于您描述的场景,其中 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"))

这里有一些替代方案。前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(数据帧)

lm( Duncan[c("income", regressors)] )

输出的 Call: 行如下所示:

Call:
lm(formula = Duncan[c("income", regressors)])

但我们可以使用以下代码使其看起来与 (1) 中的 do.call 解决方案完全相同:

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: 输出方法在这里也适用。

4) fn$ 在函数前面加上 fn$ 可以在其参数中进行字符串插值。此解决方案与问题中显示的所需语法几乎相同,使用 $ 代替 @ 来执行替换,并且灵活的替换可以很容易地扩展到更复杂的场景。代码中的 quote(Duncan) 可以写成 Duncan,它仍然是 运行,但如果使用 [=21,lm 输出中显示的 Call: 看起来会更好=].

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)))