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 primerasn
columnas son variables dependientes(y1,y2,y3,....)
y las siguientesm
columnas son variables independientes(x1+x2+x3+....)
. Paran = 3
m = 3
sefit <- lm(cbind(y1, y2, y3) ~ ., data = dat))
. Pero cómo hacer esto automáticamente, usando la estructura deldf
. Me refiero a algo como(for i in (1:n)) fit <- lm(cbind(df[something] ~ df[something], data = dat))
. Ese "algo" lo he creado conpaste
ypaste0
. 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:
-
utilizar
reformulate
; -
use
paste
/paste0
yformula
/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.