如何从一个数据框架中简洁地写出一个包含多个变量的公式?

假设我有一个响应变量和一个包含三个协变量的数据(作为一个玩具示例) :

y = c(1,4,6)
d = data.frame(x1 = c(4,-1,3), x2 = c(3,9,8), x3 = c(4,-4,-2))

我想根据数据拟合一个线性回归:

fit = lm(y ~ d$x1 + d$x2 + d$y2)

有没有一种方法可以写出公式,这样我就不用写出每个独立的协变量了?比如说

fit = lm(y ~ d)

(我希望数据框架中的每个变量都是一个协变量。)我这样问是因为我的数据框架中实际上有50个变量,所以我想避免写出 x1 + x2 + x3 + etc

162852 次浏览

是的,当然,只需添加响应 y作为数据框架中的第一列,并在其上调用 lm():

d2<-data.frame(y,d)
> d2
y x1 x2 x3
1 1  4  3  4
2 4 -1  9 -4
3 6  3  8 -2
> lm(d2)


Call:
lm(formula = d2)


Coefficients:
(Intercept)           x1           x2           x3
-5.6316       0.7895       1.1579           NA

此外,我关于 R 的信息指出,与 <-的作业是建议超过 =

在一个公式中有一个特殊的标识符,可以用来表示所有的变量,它就是 .标识符。

y <- c(1,4,6)
d <- data.frame(y = y, x1 = c(4,-1,3), x2 = c(3,9,8), x3 = c(4,-4,-2))
mod <- lm(y ~ ., data = d)

您也可以这样做,使用除了一个变量之外的所有变量(在本例中 x3被排除在外) :

mod <- lm(y ~ . - x3, data = d)

从技术上讲,.意味着 公式中已经提到的所有变量 < strong > not 。例如

lm(y ~ x1 * x2 + ., data = d)

其中 .只引用 x3,因为 x1x2已经在公式中。

另一种稍有不同的方法是从字符串创建公式。在 formula帮助页面中,您可以找到以下示例:

## Create a formula for a model with a large number of variables:
xnam <- paste("x", 1:25, sep="")
fmla <- as.formula(paste("y ~ ", paste(xnam, collapse= "+")))

然后如果你看生成的公式,你会得到:

R> fmla
y ~ x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 +
x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 + x20 + x21 +
x22 + x23 + x24 + x25

Juba 方法的一个扩展是使用 reformulate,这个函数是为这种任务明确设计的。

## Create a formula for a model with a large number of variables:
xnam <- paste("x", 1:25, sep="")


reformulate(xnam, "y")
y ~ x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 +
x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 + x20 + x21 +
x22 + x23 + x24 + x25

对于 OP 中的示例,最简单的解决方案是

# add y variable to data.frame d
d <- cbind(y, d)
reformulate(names(d)[-1], names(d[1]))
y ~ x1 + x2 + x3

或者

mod <- lm(reformulate(names(d)[-1], names(d[1])), data=d)

注意,在 d <- cbind(y, d)中将依赖变量添加到 data.frame 是首选的,不仅因为它允许使用 reformulate,还因为它允许将来在类似 predict的函数中使用 lm对象。

您可以检查包 leaps,特别是函数 regsubsets() 如文件所述:

通过穷举搜索、向前或向后逐步或顺序替换来选择模型

我构建了这个解决方案,reformulate不关心变量名是否有空格。

add_backticks = function(x) {
paste0("`", x, "`")
}


x_lm_formula = function(x) {
paste(add_backticks(x), collapse = " + ")
}


build_lm_formula = function(x, y){
if (length(y)>1){
stop("y needs to be just one variable")
}
as.formula(
paste0("`",y,"`", " ~ ", x_lm_formula(x))
)
}


# Example
df <- data.frame(
y = c(1,4,6),
x1 = c(4,-1,3),
x2 = c(3,9,8),
x3 = c(4,-4,-2)
)


# Model Specification
columns = colnames(df)
y_cols = columns[1]
x_cols = columns[2:length(columns)]
formula = build_lm_formula(x_cols, y_cols)
formula
# output
# "`y` ~ `x1` + `x2` + `x3`"


# Run Model
lm(formula = formula, data = df)
# output
Call:
lm(formula = formula, data = df)


Coefficients:
(Intercept)           x1           x2           x3
-5.6316       0.7895       1.1579           NA

```