具有任意列数的数据框的 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
,等等
我正在尝试编写一个适用于具有任意列数的数据框的函数。该功能的一部分涉及 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
,等等