¿Cómo escribir sucintamente una fórmula con muchas variables de un marco de datos?


Supongamos que tengo una variable de respuesta y un dato que contiene tres covariables (como ejemplo de juguete):

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

Quiero ajustar una regresión lineal a los datos:

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

¿Hay alguna manera de escribir la fórmula, para que no tenga que escribir cada covariable individual? Por ejemplo, algo como

fit = lm(y ~ d)

(Quiero que cada variable en el marco de datos sea una covariable.) Estoy preguntando porque en realidad tengo 50 variables en mi marco de datos, así que quiero evitar escribir x1 + x2 + x3 + etc.

Author: zx8754, 2011-03-09

6 answers

Hay un identificador especial que se puede usar en una fórmula para significar todas las variables, es el identificador ..

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)

También puedes hacer cosas como esta, para usar todas las variables barra uno:

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

Técnicamente, .significa todas las variables no ya mencionadas en la fórmula . Por ejemplo

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

Donde . solo haría referencia a x3 como x1 y x2 ya están en la fórmula.

 161
Author: Gavin Simpson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-03 14:54:04

Un enfoque ligeramente diferente es crear su fórmula a partir de una cadena. En la página de ayuda de formula encontrará el siguiente ejemplo :

## 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= "+")))

Entonces si nos fijamos en la fórmula generada, obtendrá:

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
 55
Author: juba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-09 22:20:40

Sí, por supuesto, simplemente agregue la respuesta y como primera columna en el dataframe y llame a lm() en ella:

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  

Además, mi información sobre R señala que la asignación con <- se recomienda sobre =.

 7
Author: Bernd Elkemann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-09 20:11:46

Una extensión del método de juba es usar reformulate, una función que está explícitamente diseñada para tal tarea.

## 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

Para el ejemplo en el OP, la solución más fácil aquí sería

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

O

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

Tenga en cuenta que la adición de la variable dependiente a los datos.frame in d <- cbind(y, d) es preferido no solo porque permite el uso de reformulate, sino también porque permite el uso futuro del objeto lm en funciones como predict.

 2
Author: lmo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-04 15:49:16

Construyo esta solución, reformulate no tiene cuidado si los nombres de variables tienen espacios en blanco.

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  

```

 1
Author: Christian Torrez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-15 01:12:05

Puede comprobar el paquete leaps y, en particular, la función regsubsets() funciones para la selección de modelos. Como se indica en la documentación:

Selección del modelo por búsqueda exhaustiva, paso a paso hacia adelante o hacia atrás, o reemplazo secuencial

 0
Author: amonk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-03 10:02:51