r regression linear-regression lm mlm

r - Ajuste de un modelo lineal con mĂșltiples LHS



regression linear-regression (1)

Si no te malinterpreto, estás trabajando con un conjunto de datos como este:

set.seed(0) dat <- data.frame(y1 = rnorm(30), y2 = rnorm(30), y3 = rnorm(30), x1 = rnorm(30), x2 = rnorm(30), x3 = rnorm(30))

x1 , x2 y x3 son covariables, y y1 , y2 , y3 son tres respuestas independientes. Estás intentando ajustar tres modelos lineales:

y1 ~ x1 + x2 + x3 y2 ~ x1 + x2 + x3 y3 ~ x1 + x2 + x3

Actualmente está utilizando un ciclo a través de y1 , y2 , y3 , ajustando un modelo por vez. lapply acelerar el proceso reemplazando el bucle for por lapply .

Estás en el camino equivocado. lm() es una operación costosa. Mientras su conjunto de datos no sea pequeño, los costos de for loop son insignificantes. Reemplazar el loop por lapply no proporciona ganancias de rendimiento.

Como tiene el mismo RHS (lado derecho de ~ ) para los tres modelos, la matriz del modelo es la misma para tres modelos. Por lo tanto, la factorización QR para todos los modelos solo debe hacerse una vez. lm permite esto, y puedes usar:

fit <- lm(cbind(y1, y2, y3) ~ x1 + x2 + x3, data = dat) #Coefficients: # y1 y2 y3 #(Intercept) -0.081155 0.042049 0.007261 #x1 -0.037556 0.181407 -0.070109 #x2 -0.334067 0.223742 0.015100 #x3 0.057861 -0.075975 -0.099762

Si marca str(fit) , verá que esta no es una lista de tres modelos lineales; en cambio, es un modelo lineal único con un solo objeto $qr , pero con múltiples LHS. Por lo tanto, los $coefficients , $residuals $fitted.values y $fitted.values son matrices. El modelo lineal resultante tiene una clase "mlm" adicional además de la clase "lm" habitual. mlm etiqueta mlm especial que recogía algunas preguntas sobre el tema, resumidas por su wiki de etiquetas .

Si tiene muchas más covariables, puede evitar escribir o pegar fórmulas utilizando . :

fit <- lm(cbind(y1, y2, y3) ~ ., data = dat) #Coefficients: # y1 y2 y3 #(Intercept) -0.081155 0.042049 0.007261 #x1 -0.037556 0.181407 -0.070109 #x2 -0.334067 0.223742 0.015100 #x3 0.057861 -0.075975 -0.099762

Precaución: no escriba

y1 + y2 + y3 ~ x1 + x2 + x3

Esto tratará y = y1 + y2 + y3 como una respuesta única. Use cbind() .

Seguimiento:

Estoy interesado en una generalización. Tengo un marco de datos df , donde las primeras n columnas son variables dependientes (y1,y2,y3,....) y las siguientes m columnas son variables independientes (x1+x2+x3+....) . Para n = 3 m = 3 se fit <- lm(cbind(y1, y2, y3) ~ ., data = dat)) . Pero cómo hacer esto automáticamente, usando la estructura del df . Me refiero a algo como (for i in (1:n)) fit <- lm(cbind(df[something] ~ df[something], data = dat)) . Ese "algo" lo he creado con paste y paste0 . Gracias.

Por lo tanto, está programando su fórmula o desea generar / construir dinámicamente fórmulas de modelo en el ciclo. Hay muchas formas de hacer esto, y muchas preguntas sobre el desbordamiento de pila tratan sobre esto. Normalmente hay dos enfoques:

  1. utilizar reformulate ;
  2. use paste / paste0 y formula / as.formula .

Prefiero reformulate por su pulcritud, sin embargo, no admite múltiples LHS en la fórmula. También necesita un tratamiento especial si desea transformar el LHS . Entonces, en el siguiente, usaría una solución de paste .

Para su marco de datos df , puede hacer

paste0("cbind(", paste(names(df)[1:n], collapse = ", "), ")", " ~ .")

Una forma más atractiva es usar sprintf y toString para construir el LHS:

sprintf("cbind(%s) ~ .", toString(names(df)[1:n]))

Aquí hay un ejemplo con el conjunto de datos de iris :

string_formula <- sprintf("cbind(%s) ~ .", toString(names(iris)[1:2])) # "cbind(Sepal.Length, Sepal.Width) ~ ."

Puede pasar esta fórmula de cadena a lm , ya que lm la convertirá automáticamente en una clase de fórmula. O puede hacer la coerción usted mismo usando la formula (o as.formula ):

formula(string_formula) # cbind(Sepal.Length, Sepal.Width) ~ .

Observación:

Esta fórmula LHS múltiple también es compatible en otras partes de R core:

  • el método de fórmula para la función aggregate ;
  • Análisis ANOVA con aov .

Soy nuevo en R y quiero mejorar el siguiente script con una función *apply (he leído sobre apply , pero no pude usarlo). Quiero usar la función lm en múltiples variables independientes (que son columnas en un marco de datos). solía

for (i in (1:3) { assign(paste0(''lm.'',names(data[i])), lm(formula=formula(i),data=data)) }

Formula(i) se define como

formula=function(x) { as.formula ( paste(names(data[x]),''~'', paste0(names(data[-1:-3]), collapse = ''+'')), env=parent.frame() ) }

Gracias.