如何为R中的回归量创建"宏"?

jay*_*.sf 18 r substitution lm stata stata-macros

对于长模型和重复模型,我想创建一个"宏"(所谓的Stata,并在那里完成global var1 var2 ...),其中包含模型公式的回归量.

例如来自

library(car)
lm(income ~ education + prestige, data = Duncan)
Run Code Online (Sandbox Code Playgroud)

我想要的东西:

regressors <- c("education", "prestige")
lm(income ~ @regressors, data = Duncan)  
Run Code Online (Sandbox Code Playgroud)

我能找到这种方法.但我在回归量上的应用不起作用:

reg = lm(income ~ bquote(y ~ .(regressors)), data = Duncan)
Run Code Online (Sandbox Code Playgroud)

因为它抛出了我:

Error in model.frame.default(formula = y ~ bquote(.y ~ (regressors)), data =
Duncan,  :  invalid type (language) for variable 'bquote(.y ~ (regressors))'
Run Code Online (Sandbox Code Playgroud)

即使是同一问题的公认答案:

lm(formula(paste('var ~ ', regressors)), data = Duncan)
Run Code Online (Sandbox Code Playgroud)

罢工并告诉我:

Error in model.frame.default(formula = formula(paste("var ~ ", regressors)),
: object is not a matrix`. 
Run Code Online (Sandbox Code Playgroud)

当然我试过as.matrix(regressors):)

那么,我还能做些什么呢?

G. *_*eck 20

这是一些替代方案.前3个没有使用包.

1)重新制定

fo <- reformulate(regressors, response = "income")
lm(fo, Duncan)
Run Code Online (Sandbox Code Playgroud)

或者您可能希望将最后一行写为此,以便输出中显示的公式看起来更好:

do.call("lm", list(fo, quote(Duncan)))
Run Code Online (Sandbox Code Playgroud)

在这种情况下,输出的Call:行显示为预期,即:

Call:
lm(formula = income ~ education + prestige, data = Duncan)
Run Code Online (Sandbox Code Playgroud)

2)lm(数据帧)

lm( Duncan[c("income", regressors)] )
Run Code Online (Sandbox Code Playgroud)

输出的Call:行如下所示:

Call:
lm(formula = Duncan[c("income", regressors)])
Run Code Online (Sandbox Code Playgroud)

但我们可以do.call使用以下代码使其与(1)中的解决方案完全一致:

fo <- formula(model.frame(income ~., Duncan[c("income", regressors)]))
do.call("lm", list(fo, quote(Duncan)))
Run Code Online (Sandbox Code Playgroud)

3)点

类似于@jenesaisquoi在评论中提出的替代方案是:

lm(income ~., Duncan[c("income", regressors)])
Run Code Online (Sandbox Code Playgroud)

(2)中对Call:输出中讨论的方法也适用于此处.

4)fn $ 使用fn $预设函数可在其参数中启用字符串插值.这个解决方案与问题中显示的所需语法几乎相同,使用$代替@来执行替换,灵活的替换可以很容易地扩展到更复杂的场景.该quote(Duncan)代码可以写成只Duncan和它仍然会运行,但呼叫:在显示lm输出会更好看,如果你使用quote(Duncan).

library(gsubfn)

rhs <- paste(regressors, collapse = "+")
fn$lm("income ~ $rhs", quote(Duncan))
Run Code Online (Sandbox Code Playgroud)

Call:行看起来几乎与do.call上面的解决方案相同- 只有间距和引号不同:

Call:
lm(formula = "income ~ education+prestige", data = Duncan)
Run Code Online (Sandbox Code Playgroud)

如果你想要它绝对相同那么:

fo <- fn$formula("income ~ $rhs")
do.call("lm", list(fo, quote(Duncan)))
Run Code Online (Sandbox Code Playgroud)


小智 12

对于您描述的场景,regressors全局环境中的位置,您可以使用:

lm(as.formula(paste("income~", paste(regressors, collapse="+"))), data = 
Duncan)
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用一个函数:

modincome <- function(regressors){
    lm(as.formula(paste("income~", paste(regressors, collapse="+"))), data = 
Duncan)  
}

modincome(c("education", "prestige"))
Run Code Online (Sandbox Code Playgroud)