2011-03-09 10 views
90

Supongamos que tengo una variable de respuesta y una que contiene tres covariables de datos (como un ejemplo de juguete):¿Cómo escribir sucintamente una fórmula con muchas variables de un marco de datos?

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

quiero para ajustar una regresión lineal para los datos:

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

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

fit = lm(y ~ d) 

(Quiero que cada variable en la trama de datos a ser una covariable.) Lo digo porque en realidad tengo 50 variables en mi trama de datos, por lo que quiero evitar escribir x1 + x2 + x3 + etc .

+3

posible duplicado de [Especificación de fórmula en R con GLM sin declaración explícita de cada covariable] (http://stackoverflow.com/questions/3588961/specifying-formula-in-r -with-glm-without-explicit-declaration-of-each-covariate) –

+1

Consulte también [cómo insertar el nombre de la columna del marco de datos en la ecuación] (http://stackoverflow.com/questions/25954361/how-to-insert-dataframe -columna-nombre-en-ecuación-r). – lmo

Respuesta

148

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 puede hacer cosas como esta, a utilizar todas las variables excepto uno:

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

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

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

donde . solamente haría referencia como x1 y x2 ya están en la fórmula.

+0

El marco de datos 'd' tiene 4 columnas (y, x1, x2 y x3). Entonces, si la fórmula es "y ~.", ¿El lado derecho significa "todas las columnas", excepto las enumeradas en el lado izquierdo? – stackoverflowuser2010

+1

@ stackoverflowuser2010 Sí, '.' técnicamente significa que todas las variables en' data' * no están ya en la fórmula *. –

+0

¿Esto también funcionaría para una lista? – theforestecologist

7

Sí, por supuesto, sólo tiene que añadir la respuesta y como primera columna de la trama de datos y llamar lm() en él:

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 más que =.

+0

¡Gracias! Sí, sé que todos siempre dicen que usen <-, pero nadie dice nunca por qué y = es más fácil escribir =). – grautur

+2

@gratur Una razón es que cosas como 'foo (bar <- 1:10)' funcionan (y 'bar' se crea) pero' foo (bar = 1:10) 'puede fallar porque' bar' no es un argumento de 'foo' y tampoco creará' barra'. –

+2

¿Por qué el coeficiente de 'x3'' NA'? – ziyuang

51

Un enfoque ligeramente diferente es crear su fórmula a partir de una cadena. En la página formula ayuda se encuentra 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 
+1

Esto funciona muy bien para leer estos valores de un archivo. ¡Gracias! –

2

Una extensión del método de Juba es utilizar 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 PO, 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 de los datos.marco en 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.

0

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

Modelo de búsqueda exhaustiva, hacia delante o por pasos hacia atrás, o la sustitución secuencial

1

construyo esta solución, reformulate no cuidar 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 

`` `

Cuestiones relacionadas