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


127

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

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



Answers:


202

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

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)

从技术上讲,.是指所有的变量不是公式中已经提到。例如

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

其中.只引用x3作为x1x2已在公式中。


数据帧“ d”具有4列(y,x1,x2和x3)。因此,如果公式为“ y〜。”,则除左侧列出的列之外,右侧是否表示“所有列”?
stackoverflowuser2010 2014年

1
@ stackoverflowuser2010是的,从.技术上讲,意味着data 公式中尚未存在的所有变量。
加文·辛普森

1
@theforestecologist如果您的意思data是一个列表,可以从该列表中查找公式中的变量,则可以。数据框,列表或环境是该data参数的可接受选项。如果这不是您的意思,则需要进一步扩展。
加文·辛普森

@加文 这就是我的意思。谢谢。我该如何使用data [[x]]作为列出的变量与实际变量名称(例如'x3')的比较?例如,我将如何进行以下工作?lm(d[[1]] ~ d[[3]] + ., data = d)
–forestecologist

它不在names列表中;说你有ll <- list(y = rnorm(10), x = rnorm(10), z = rnorm(10), zz = runif(10)),那么以下工作:lm(y ~ x + ., data = ll)。因此,除非有足够的理由,否则没有太多理由让您拥有这样的数据,但是它可以工作。公式中元素的长度必须相同,这对列表中的内容施加了一些限制。更复杂的对象可能需要代码来提取所需的元素。如果d[[1]]是数据框/矩阵,则需要代码才能完成该工作
Gavin Simpson

66

稍微不同的方法是从字符串创建公式。在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

1
这对于从文件中读取这些值非常有效。谢谢!
Ben Sidhom

请注意,as.formula部分是必需的部分
Jinhua Wang

7

是的,当然,只需将响应添加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的信息指出,<-建议使用=


谢谢!是的,我知道每个人都总是说使用<-,但是没有人说过为什么和=更容易键入=)。
grautur 2011年

2
@gratur一个原因是像foo(bar <- 1:10)工作(和bar被创建)之类的东西foo(bar = 1:10)会失败,因为它既bar不是参数foo又不会创建bar
加文·辛普森

2
为什么是系数x3 NA
ziyuang

6

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)

请注意,将因变量添加到data.frame中d <- cbind(y, d)是首选方法,这不仅因为它允许使用reformulate,而且还因为它允许将来lm在诸如之类的函数中使用该对象predict


2

我构建了此解决方案,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  

```


0

您可以检查包装leaps,尤其是regsubsets() 用于型号选择的功能功能。如文档中所述:

通过详尽搜索,向前或向后逐步搜索或顺序替换来选择模型

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.