我正在尝试编写一个适用于具有任意列数的数据框的函数。该函数的一部分涉及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&x和s上的二阶多项式中包含y的回归,但它必须在x的数量方面具有灵活性。和z由用户提供。
我知道如果我能直接观察df,那么我可以简单地使用
linear.model <- lm(y ~ cbind(x1,x2) + poly(cbind(z1,z2),degree=2),data=df)
但在某些情况下,可能会有更多或更少的x和/或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和s和z所在的位置。
非常感谢您的帮助。谢谢!
答案 0 :(得分:2)
您可以从数据框名称和字符串中创建字符串
将其转换为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)
答案 1 :(得分:2)
这是另一种选择。代码更复杂,但我认为最终结果更容易理解。
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
等。