具有任意列数的数据框的 lm 函数

lm function for a dataframe with arbitrary number of columns

我正在尝试编写一个适用于具有任意列数的数据框的函数。该功能的一部分涉及 lm 命令,我遇到了一个并发症。对于此示例,我将使用以下数据:

x1 <- runif(100)
x2 <- runif(100)

z1 <- runif(100)
z2 <- runif(100)

y <- 0.2 + 0.7*x1 + 0.7*x2 + 0.4*z1 + 0.4*z2 + 0.8*z1*z2 + 0.8*z1^2 + 0.8*z2^2 + rnorm(100,0,.2) 

df <- data.frame(y,x1,x2,z1,z2)

该函数被编程为记录用户提供了多少个x和多少个z,并且x总是出现在数据框中单个y变量之后和z变量之前的情况.所以在这种情况下,数据框的第一列中有 2 个 x 和 2 个 z,当然还有 1 个 y。函数记录x和z的个数作为变量n.x和n.z

n.x <- 2
n.z <- 2

我想在 x 和 z 中的二阶多项式上包括 y 的回归,但它必须灵活地考虑用户提供的 x 和 z 的数量。

我知道如果我能够直接观察 df,那么我可以简单地使用

linear.model <- lm(y ~ cbind(x1,x2) + poly(cbind(z1,z2),degree=2),data=df) 

但在某些情况下,可能会有更多或更少的 x and/or z。我尝试了以下方法,知道它不太可能起作用:

linear.model <- lm(df$y ~ cbind(df[,2:(n.x+1)]) + poly(cbind(df[,(n.x+2):(n.x+n.z+1)]),degree=2)) 

当然没用。这个问题的关键是它必须使用 lm 中的 n.x 和 n.z 变量来指示数据框中 x 和 z 的位置。

非常感谢您的帮助。谢谢!

您可以从数据框名称和 用 as.formula:

转换
xs <- paste(names(df)[2:(1 + n.x)], collapse = ", ")
zs <- paste(names(df)[(2 + n.x):(1 + n.x + n.z)], collapse = ", ")

s_formula <- sprintf("y ~ cbind(%s) + poly(cbind(%s),degree=2)", xs, zs)

linear.model <- lm(as.formula(s_formula), data=df)

这是另一个选项。我认为代码比较复杂,但最终结果更容易解释。

cn <- colnames(df)
zz <- cn[grepl("^z",cn)]
xx <- cn[grepl("^x",cn)]
form <- paste0("y~",
               paste(paste(paste(xx,collapse="+")),
                     paste(zz,collapse="*"),
                     paste(paste0("I(",zz,"^2)"),collapse="+"), 
                     sep="+"))
form
# [1] "y~x1+x2+z1*z2+I(z1^2)+I(z2^2)
fit <- lm(as.formula(form),df)
coef(summary(fit))
#               Estimate Std. Error    t value     Pr(>|t|)
# (Intercept) 0.20295008 0.11381558 1.78314847 7.786013e-02
# x1          0.68572092 0.08322408 8.23945324 1.141453e-12
# x2          0.70859080 0.07803392 9.08054860 1.964402e-14
# z1          0.74963604 0.32518472 2.30526218 2.340025e-02
# z2          0.01230116 0.34891211 0.03525577 9.719522e-01
# I(z1^2)     0.50320062 0.31074776 1.61932181 1.088012e-01
# I(z2^2)     1.13595678 0.30034582 3.78216276 2.762723e-04
# z1:z2       0.86561996 0.28552946 3.03163095 3.159388e-03

请注意,在 lm(...) 的公式参数中,* 运算符会生成所有线性项和交叉项,因此,例如,z1*z2*z3 将生成所有项 z1 + z2 + z3 + z1:z2 + z1:z3 + z2:z3,等等