Esta clase desarrolla la regresión lineal múltiple como una ampliación de la regresión lineal simple y, simultáneamente, como una instancia del Modelo Lineal General. La idea central es que regresión, ANOVA y ANCOVA comparten una misma estructura:
\[ \text{Datos} = \text{Modelo} + \text{Error}. \]
La regresión utiliza predictores cuantitativos y también puede incorporar predictores cualitativos mediante variables indicadoras. Cuando el modelo contiene únicamente factores, puede representar un ANOVA. Cuando combina factores y covariables cuantitativas, puede representar un ANCOVA.
En regresión lineal simple se utiliza una sola variable independiente. En regresión múltiple se estudia una variable dependiente \(Y\) a partir de \(p\) variables independientes:
\[ Y_i = \beta_0+\beta_1X_{1i}+\beta_2X_{2i}+\cdots+\beta_pX_{pi}+\varepsilon_i. \]
La ecuación de regresión poblacional es:
\[ E(Y\mid X_1,\ldots,X_p) = \beta_0+\beta_1X_1+\cdots+\beta_pX_p. \]
La ecuación estimada mediante una muestra es:
\[ \widehat{Y}_i = b_0+b_1X_{1i}+\cdots+b_pX_{pi}. \]
El residual de la observación \(i\) es:
\[ e_i=Y_i-\widehat{Y}_i. \]
En un modelo múltiple, \(b_j\) representa el cambio esperado en \(Y\) ante un aumento de una unidad en \(X_j\), manteniendo constantes las demás variables incluidas en el modelo.
Esta última frase es indispensable. El coeficiente múltiple no describe necesariamente la relación marginal entre \(X_j\) y \(Y\). Describe una relación parcial o condicional, después de controlar estadísticamente los otros predictores.
Error frecuente: interpretar un coeficiente como causal. Un modelo de regresión puede estimar asociaciones ajustadas, pero la causalidad requiere un diseño, supuestos y una estrategia de identificación adecuados.
La palabra lineal se refiere a que el modelo es lineal en los parámetros \(\beta\). Por ejemplo, los modelos siguientes siguen siendo modelos lineales:
\[ Y=\beta_0+\beta_1X+\beta_2X^2+\varepsilon, \]
\[ Y=\beta_0+\beta_1X+\beta_2Z+\beta_3XZ+\varepsilon. \]
El primero permite curvatura y el segundo permite interacción. En ambos casos, los parámetros aparecen de forma lineal.
Se construirá una cartera simulada de pólizas de automóvil. El objetivo es explicar y predecir el costo anual de siniestros a partir de características del vehículo, exposición y perfil del conductor.
Las variables serán:
costo_siniestros: costo anual observado.valor_vehiculo_10k: valor del vehículo en unidades de
10 000.kilometraje_1000: kilometraje anual en kilometros.edad: edad del conductor.experiencia: años aproximados de experiencia de
conducción.zona: zona de riesgo, baja, media o alta.tipo_vehiculo: sedán, SUV o pickup.set.seed(1501)
n <- 220
zona <- factor(
sample(
c("Baja", "Media", "Alta"),
size = n,
replace = TRUE,
prob = c(0.35, 0.40, 0.25)
),
levels = c("Baja", "Media", "Alta")
)
tipo_vehiculo <- factor(
sample(
c("Sedan", "SUV", "Pickup"),
size = n,
replace = TRUE,
prob = c(0.50, 0.30, 0.20)
),
levels = c("Sedan", "SUV", "Pickup")
)
edad <- round(runif(n, min = 18, max = 70))
edad_licencia <- sample(16:22, size = n, replace = TRUE)
experiencia <- pmax(
0,
edad - edad_licencia + round(rnorm(n, mean = 0, sd = 2))
)
valor_vehiculo <- round(
exp(rnorm(n, mean = log(90000), sd = 0.45)),
digits = -2
)
valor_vehiculo <- pmin(pmax(valor_vehiculo, 25000), 300000)
kilometraje <- round(runif(n, min = 5000, max = 35000))
efecto_zona <- c(Baja = 0, Media = 450, Alta = 1000)[as.character(zona)]
efecto_tipo <- c(Sedan = 0, SUV = 300, Pickup = 550)[as.character(tipo_vehiculo)]
# La zona alta presenta además una pendiente mayor respecto del kilometraje.
efecto_interaccion <- ifelse(
zona == "Alta",
25 * ((kilometraje / 1000) - mean(kilometraje / 1000)),
0
)
costo_siniestros <- (
600 +
220 * (valor_vehiculo / 10000) +
28 * (kilometraje / 1000) -
7 * edad +
efecto_zona +
efecto_tipo +
efecto_interaccion +
rnorm(n, mean = 0, sd = 700)
)
costo_siniestros <- round(pmax(costo_siniestros, 200), digits = 2)
polizas <- data.frame(
costo_siniestros = costo_siniestros,
valor_vehiculo_10k = valor_vehiculo / 10000,
kilometraje_1000 = kilometraje / 1000,
edad = edad,
experiencia = experiencia,
zona = zona,
tipo_vehiculo = tipo_vehiculo
)
head(polizas)## costo_siniestros valor_vehiculo_10k kilometraje_1000 edad experiencia zona
## Min. : 431.2 Min. : 2.500 Min. : 5.12 Min. :18.00 Min. : 0.00 Baja :84
## 1st Qu.:2713.4 1st Qu.: 6.657 1st Qu.:12.55 1st Qu.:33.75 1st Qu.:15.00 Media:73
## Median :3401.0 Median : 8.875 Median :20.35 Median :47.00 Median :28.00 Alta :63
## Mean :3625.7 Mean : 9.893 Mean :20.02 Mean :45.66 Mean :26.80
## 3rd Qu.:4353.1 3rd Qu.:12.315 3rd Qu.:27.10 3rd Qu.:58.00 3rd Qu.:39.25
## Max. :9825.6 Max. :30.000 Max. :34.94 Max. :70.00 Max. :56.00
## tipo_vehiculo
## Sedan :116
## SUV : 60
## Pickup: 44
##
##
##
variables_numericas <- polizas[
c(
"costo_siniestros",
"valor_vehiculo_10k",
"kilometraje_1000",
"edad",
"experiencia"
)
]
round(cor(variables_numericas), 3)## costo_siniestros valor_vehiculo_10k kilometraje_1000 edad experiencia
## costo_siniestros 1.000 0.762 0.211 -0.040 -0.044
## valor_vehiculo_10k 0.762 1.000 0.008 -0.052 -0.062
## kilometraje_1000 0.211 0.008 1.000 0.065 0.062
## edad -0.040 -0.052 0.065 1.000 0.982
## experiencia -0.044 -0.062 0.062 0.982 1.000
par(mfrow = c(1, 3))
plot(
polizas$valor_vehiculo_10k,
polizas$costo_siniestros,
xlab = "Valor del vehículo, unidades de 10 000",
ylab = "Costo anual de siniestros",
main = "Costo y valor del vehículo",
pch = 19
)
plot(
polizas$kilometraje_1000,
polizas$costo_siniestros,
xlab = "Kilometraje anual, miles",
ylab = "Costo anual de siniestros",
main = "Costo y kilometraje",
pch = 19
)
boxplot(
costo_siniestros ~ zona,
data = polizas,
xlab = "Zona",
ylab = "Costo anual de siniestros",
main = "Costo por zona"
)Comprobación 1. Antes de ajustar un modelo, indique cuáles predictores parecen tener asociación con el costo. ¿La gráfica permite concluir que una asociación es causal?
El valor del vehículo, el kilometraje y la zona deberían mostrar asociaciones visibles. Sin embargo, una gráfica bivariada no controla otros factores y no demuestra causalidad. La asociación observada puede cambiar cuando se incorporan predictores correlacionados.
El método de mínimos cuadrados ordinarios selecciona los coeficientes que minimizan:
\[ SCE=\sum_{i=1}^{n}(Y_i-\widehat{Y}_i)^2 =\sum_{i=1}^{n}e_i^2. \]
En notación matricial:
\[ \mathbf{Y}=\mathbf{X}\boldsymbol{\beta}+\boldsymbol{\varepsilon}, \]
y, cuando \(\mathbf{X}'\mathbf{X}\) es invertible,
\[ \widehat{\boldsymbol{\beta}} = (\mathbf{X}'\mathbf{X})^{-1}\mathbf{X}'\mathbf{Y}. \]
R realiza este cálculo con lm().
modelo_1 <- lm(
costo_siniestros ~ valor_vehiculo_10k + kilometraje_1000 + edad,
data = polizas
)
summary(modelo_1)##
## Call:
## lm(formula = costo_siniestros ~ valor_vehiculo_10k + kilometraje_1000 +
## edad, data = polizas)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2673.59 -565.75 -19.45 567.69 2340.14
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 845.557 259.009 3.265 0.00127 **
## valor_vehiculo_10k 220.464 12.151 18.143 < 0.0000000000000002 ***
## kilometraje_1000 32.795 6.668 4.918 0.00000173 ***
## edad -1.257 3.960 -0.317 0.75120
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 854.9 on 216 degrees of freedom
## Multiple R-squared: 0.6226, Adjusted R-squared: 0.6173
## F-statistic: 118.8 on 3 and 216 DF, p-value: < 0.00000000000000022
tabla_coeficientes <- function(modelo, digitos = 4) {
tabla <- as.data.frame(coef(summary(modelo)))
tabla$termino <- rownames(tabla)
rownames(tabla) <- NULL
tabla <- tabla[
c("termino", "Estimate", "Std. Error", "t value", "Pr(>|t|)")
]
names(tabla) <- c(
"Término",
"Estimación",
"Error estándar",
"Estadístico t",
"Valor p"
)
columnas_numericas <- 2:ncol(tabla)
tabla[columnas_numericas] <- lapply(
tabla[columnas_numericas],
round,
digits = digitos
)
tabla
}
knitr::kable(
tabla_coeficientes(modelo_1),
caption = "Coeficientes del modelo múltiple inicial"
)| Término | Estimación | Error estándar | Estadístico t | Valor p |
|---|---|---|---|---|
| (Intercept) | 845.5570 | 259.0090 | 3.2646 | 0.0013 |
| valor_vehiculo_10k | 220.4641 | 12.1513 | 18.1433 | 0.0000 |
| kilometraje_1000 | 32.7954 | 6.6685 | 4.9180 | 0.0000 |
| edad | -1.2571 | 3.9597 | -0.3175 | 0.7512 |
Para interpretar un coeficiente:
Ejemplo de redacción:
Manteniendo constantes el kilometraje y la edad, un aumento de 10 000 unidades monetarias en el valor del vehículo se asocia con un cambio promedio de \(b_1\) unidades monetarias en el costo anual de siniestros.
El intercepto representa la respuesta esperada cuando todos los predictores cuantitativos valen cero y los factores se encuentran en sus categorías de referencia. Puede carecer de interpretación práctica cuando el valor cero está fuera del rango observado.
Centrar una variable significa restarle una constante, usualmente su media:
\[ X_c=X-\overline{X}. \]
El centrado no cambia las predicciones ni el ajuste global. Sí cambia la interpretación del intercepto y de los efectos principales en modelos con interacción.
polizas$valor_c <- (
polizas$valor_vehiculo_10k -
mean(polizas$valor_vehiculo_10k)
)
polizas$km_c <- (
polizas$kilometraje_1000 -
mean(polizas$kilometraje_1000)
)
polizas$edad_c <- polizas$edad - mean(polizas$edad)
modelo_1_centrado <- lm(
costo_siniestros ~ valor_c + km_c + edad_c,
data = polizas
)
coef(modelo_1)## (Intercept) valor_vehiculo_10k kilometraje_1000 edad
## 845.557029 220.464138 32.795431 -1.257063
## (Intercept) valor_c km_c edad_c
## 3625.727455 220.464138 32.795431 -1.257063
## [1] TRUE
Comprobación 2. ¿Por qué cambió el intercepto después de centrar las variables, pero no cambiaron los valores ajustados?
El centrado cambia el punto de origen de los predictores. En el modelo centrado, el intercepto corresponde al costo esperado para una póliza con valores promedio en los predictores. La superficie ajustada es la misma, únicamente se reparametriza.
La variabilidad total puede descomponerse en:
\[ STC=SCR+SCE, \]
donde:
El coeficiente de determinación múltiple es:
\[ R^2=\frac{SCR}{STC}=1-\frac{SCE}{STC}. \]
Representa la proporción de variabilidad muestral de \(Y\) explicada por el modelo.
y <- polizas$costo_siniestros
y_ajustada <- fitted(modelo_1)
residuales <- residuals(modelo_1)
STC <- sum((y - mean(y))^2)
SCR <- sum((y_ajustada - mean(y))^2)
SCE <- sum(residuales^2)
c(STC = STC, SCR = SCR, SCE = SCE)## STC SCR SCE
## 418216587 260362449 157854138
## STC SCR_mas_SCE
## 418216587 418216587
## R2_manual R2_R
## 0.6225541 0.6225541
Agregar predictores nunca reduce \(R^2\), incluso cuando el nuevo predictor aporta poco. Por ello se utiliza:
\[ R^2_{\text{ajustado}} = 1-(1-R^2)\frac{n-1}{n-p-1}. \]
Este indicador penaliza la inclusión de predictores adicionales.
## [1] 0.6173118
Un \(R^2\) alto no garantiza que el modelo sea correcto, causal, estable o útil fuera de la muestra. Un \(R^2\) bajo tampoco invalida automáticamente un efecto científicamente importante.
La prueba \(F\) global evalúa:
\[ H_0:\beta_1=\beta_2=\cdots=\beta_p=0, \]
contra:
\[ H_a:\text{al menos uno de los coeficientes de pendiente es distinto de cero}. \]
El estadístico es:
\[ F=\frac{CMR}{CME} = \frac{SCR/p}{SCE/(n-p-1)}. \]
## value numdf dendf
## 118.7558 3.0000 216.0000
Para cada predictor:
\[ H_0:\beta_j=0, \qquad H_a:\beta_j\neq 0, \]
con:
\[ t=\frac{b_j}{SE(b_j)}. \]
## 2.5 % 97.5 %
## (Intercept) 335.04835 1356.065710
## valor_vehiculo_10k 196.51393 244.414349
## kilometraje_1000 19.65179 45.939069
## edad -9.06174 6.547614
Sí. La prueba \(F\) evalúa el conjunto de predictores. Las pruebas \(t\) evalúan coeficientes individuales condicionados a los demás predictores. La discrepancia puede surgir por:
Comprobación 3. Explique por qué no debe concluirse que “el modelo no sirve” únicamente porque uno de sus coeficientes tenga un valor \(p\) mayor que 0.05.
El valor \(p\) individual responde si existe evidencia de que un coeficiente parcial difiere de cero, dado el resto del modelo. No evalúa por sí solo el desempeño predictivo, la relevancia sustantiva, la calidad del diseño, la precisión de otros coeficientes ni la significancia global.
Una idea central del enfoque del Modelo Lineal General es evaluar un efecto comparando:
La pregunta es:
¿Cuánto se reduce el error al agregar el conjunto de términos?
Suponga que el modelo reducido tiene suma de cuadrados del error \(SCE_R\) y el completo \(SCE_C\). La reducción atribuible a los términos agregados es:
\[ SCE_R-SCE_C. \]
La prueba parcial \(F\) es:
\[ F= \frac{(SCE_R-SCE_C)/q} {SCE_C/(n-p_C-1)}, \]
donde \(q\) es el número de parámetros agregados.
modelo_reducido <- lm(
costo_siniestros ~ valor_c + km_c + edad_c,
data = polizas
)
modelo_completo <- lm(
costo_siniestros ~ valor_c + km_c + edad_c + zona,
data = polizas
)
anova(modelo_reducido, modelo_completo)anova(modelo_reducido, modelo_completo) realiza una
prueba \(F\) parcial. En este ejemplo,
la zona requiere dos coeficientes porque tiene tres niveles y uno
funciona como categoría de referencia.
R2_reducido <- summary(modelo_reducido)$r.squared
R2_completo <- summary(modelo_completo)$r.squared
delta_R2 <- R2_completo - R2_reducido
R2_parcial <- (
deviance(modelo_reducido) - deviance(modelo_completo)
) / deviance(modelo_reducido)
c(
R2_reducido = R2_reducido,
R2_completo = R2_completo,
cambio_R2 = delta_R2,
R2_parcial_zona = R2_parcial
)## R2_reducido R2_completo cambio_R2 R2_parcial_zona
## 0.6225541 0.7094446 0.0868905 0.2302065
El cambio en \(R^2\) mide cuánto aumenta la proporción total explicada. El \(R^2\) parcial mide la proporción del error del modelo reducido que desaparece al agregar el efecto.
drop1() elimina un término por vez y compara el modelo
resultante con el modelo completo. Para un predictor numérico con un
grado de libertad, la prueba parcial \(F\) es equivalente al cuadrado de la prueba
\(t\):
\[ F=t^2. \]
t_edad <- coef(summary(modelo_completo))["edad_c", "t value"]
modelo_sin_edad <- update(modelo_completo, . ~ . - edad_c)
F_edad <- anova(modelo_sin_edad, modelo_completo)$F[2]
c(t_cuadrado = t_edad^2, F_parcial = F_edad)## t_cuadrado F_parcial
## 1.315186 1.315186
En diseños no ortogonales o con predictores correlacionados, la variabilidad explicada por dos predictores puede superponerse. Por ello es necesario indicar qué hipótesis se está probando.
La tabla producida por anova(modelo) en R asigna la
variabilidad en el orden de entrada de los términos. Estas son sumas de
cuadrados secuenciales o Tipo I.
modelo_orden_1 <- lm(
costo_siniestros ~ edad + experiencia + zona,
data = polizas
)
modelo_orden_2 <- lm(
costo_siniestros ~ experiencia + edad + zona,
data = polizas
)
anova(modelo_orden_1)Como edad y experiencia están
correlacionadas, el predictor que entra primero puede recibir una parte
importante de la variabilidad compartida.
Estas pruebas preguntan qué aporta cada término después de controlar por todos los demás términos incluidos.
Regla conceptual: no elija un tipo de suma de cuadrados únicamente porque produzca un valor \(p\) conveniente. Defina primero la hipótesis científica, la jerarquía del modelo y el orden lógico de ajuste.
La regresión puede incorporar variables cualitativas. Si un factor tiene \(k\) categorías, se requieren normalmente \(k-1\) columnas para evitar sobreparametrización.
R utiliza por defecto contrastes de tratamiento. La primera categoría del factor es la referencia.
## Media Alta
## Baja 0 0
## Media 1 0
## Alta 0 1
## (Intercept) zonaMedia zonaAlta
## 1 1 1 0
## 2 1 1 0
## 3 1 0 1
## 4 1 1 0
## 5 1 0 0
## 6 1 1 0
Para zona con referencia "Baja":
zonaMedia representa la diferencia entre media y
baja;zonaAlta representa la diferencia entre alta y
baja.modelo_2 <- lm(
costo_siniestros ~
valor_c +
km_c +
edad_c +
zona +
tipo_vehiculo,
data = polizas
)
knitr::kable(
tabla_coeficientes(modelo_2),
caption = "Modelo con predictores cuantitativos y cualitativos"
)| Término | Estimación | Error estándar | Estadístico t | Valor p |
|---|---|---|---|---|
| (Intercept) | 3032.2671 | 94.0683 | 32.2348 | 0.0000 |
| valor_c | 216.0369 | 10.3912 | 20.7903 | 0.0000 |
| km_c | 34.2100 | 5.6786 | 6.0244 | 0.0000 |
| edad_c | -6.0754 | 3.4027 | -1.7854 | 0.0756 |
| zonaMedia | 329.1864 | 117.0294 | 2.8129 | 0.0054 |
| zonaAlta | 973.0689 | 121.7584 | 7.9918 | 0.0000 |
| tipo_vehiculoSUV | 366.3744 | 116.4605 | 3.1459 | 0.0019 |
| tipo_vehiculoPickup | 528.2923 | 131.4540 | 4.0188 | 0.0001 |
polizas$zona_ref_alta <- relevel(polizas$zona, ref = "Alta")
modelo_ref_alta <- lm(
costo_siniestros ~ valor_c + km_c + edad_c + zona_ref_alta,
data = polizas
)
coef(modelo_completo)## (Intercept) valor_c km_c edad_c zonaMedia zonaAlta
## 3252.864068 212.848576 33.111506 -4.026183 264.631107 995.426575
## (Intercept) valor_c km_c edad_c zona_ref_altaBaja
## 4248.290643 212.848576 33.111506 -4.026183 -995.426575
## zona_ref_altaMedia
## -730.795468
## [1] TRUE
Cambiar la referencia modifica la parametrización y las comparaciones individuales, pero no cambia los valores ajustados, los residuales, \(R^2\) ni la prueba global del factor.
Con contrastes de suma, los coeficientes comparan niveles respecto de una media general parametrizada.
polizas$zona_suma <- polizas$zona
contrasts(polizas$zona_suma) <- contr.sum(3)
modelo_suma <- lm(
costo_siniestros ~ valor_c + km_c + edad_c + zona_suma,
data = polizas
)
model.matrix(modelo_suma)[1:8, ]## (Intercept) valor_c km_c edad_c zona_suma1 zona_suma2
## 1 1 -2.672636 7.114064 22.340909 0 1
## 2 1 -1.312636 13.917064 -24.659091 0 1
## 3 1 20.107364 -7.214936 -20.659091 -1 -1
## 4 1 -3.892636 7.070064 -12.659091 0 1
## 5 1 -2.162636 2.150064 6.340909 1 0
## 6 1 1.157364 -14.900936 5.340909 0 1
## 7 1 -2.122636 3.066064 15.340909 0 1
## 8 1 2.747364 -2.600936 -15.659091 1 0
## (Intercept) valor_c km_c edad_c zona_suma1 zona_suma2
## 3672.883295 212.848576 33.111506 -4.026183 -420.019228 -155.388120
## [1] TRUE
Un ANOVA de un factor puede escribirse como una regresión que utiliza únicamente un predictor cualitativo:
\[ Y_i=\beta_0+\beta_1D_{1i}+\cdots+\beta_{k-1}D_{k-1,i}+\varepsilon_i. \]
##
## Call:
## lm(formula = costo_siniestros ~ zona, data = polizas)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3945.3 -770.2 -111.0 718.8 5449.2
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 3199.6 141.6 22.591 < 0.0000000000000002 ***
## zonaMedia 268.5 207.7 1.293 0.197
## zonaAlta 1176.8 216.3 5.439 0.000000144 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1298 on 217 degrees of freedom
## Multiple R-squared: 0.1257, Adjusted R-squared: 0.1176
## F-statistic: 15.6 on 2 and 217 DF, p-value: 0.0000004682
La prueba \(F\) de
anova(modelo_anova) evalúa la igualdad de las medias
poblacionales de las zonas.
modelo_intercepto <- lm(
costo_siniestros ~ 1,
data = polizas
)
anova(modelo_intercepto, modelo_anova)El modelo reducido contiene solo una media general. El modelo completo permite medias diferentes por zona. La reducción del error es la variabilidad entre grupos.
El ANCOVA combina:
Un modelo básico es:
\[ Y_i = \beta_0+ \beta_1D_{1i}+\cdots+ \beta_{k-1}D_{k-1,i}+ \gamma X_i+ \varepsilon_i. \]
El efecto del factor se evalúa después de controlar la covariable.
modelo_ancova <- lm(
costo_siniestros ~ zona + valor_c + km_c + edad_c,
data = polizas
)
summary(modelo_ancova)##
## Call:
## lm(formula = costo_siniestros ~ zona + valor_c + km_c + edad_c,
## data = polizas)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2271.94 -525.81 3.67 522.46 1860.62
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 3252.864 82.535 39.412 < 0.0000000000000002 ***
## zonaMedia 264.631 120.931 2.188 0.0297 *
## zonaAlta 995.427 126.661 7.859 0.000000000000187 ***
## valor_c 212.849 10.757 19.788 < 0.0000000000000002 ***
## km_c 33.112 5.881 5.630 0.000000056252382 ***
## edad_c -4.026 3.511 -1.147 0.2527
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 753.5 on 214 degrees of freedom
## Multiple R-squared: 0.7094, Adjusted R-squared: 0.7027
## F-statistic: 104.5 on 5 and 214 DF, p-value: < 0.00000000000000022
La prueba del factor zona compara respuestas ajustadas a
valores comunes de las covariables.
Como las covariables fueron centradas, el valor cero representa su media. Se pueden obtener respuestas ajustadas por zona:
escenario_zonas <- data.frame(
zona = factor(
levels(polizas$zona),
levels = levels(polizas$zona)
),
valor_c = 0,
km_c = 0,
edad_c = 0
)
medias_ajustadas <- predict(
modelo_ancova,
newdata = escenario_zonas,
interval = "confidence",
level = 0.95
)
resultado_ajustado <- cbind(
escenario_zonas["zona"],
as.data.frame(medias_ajustadas)
)
knitr::kable(
resultado_ajustado,
digits = 2,
caption = "Costos medios ajustados por zona"
)| zona | fit | lwr | upr |
|---|---|---|---|
| Baja | 3252.86 | 3090.18 | 3415.55 |
| Media | 3517.50 | 3343.44 | 3691.55 |
| Alta | 4248.29 | 4060.17 | 4436.41 |
Las medias ajustadas son predicciones del modelo para valores específicos de las covariables. Debe indicarse siempre en qué valores se realizó el ajuste.
El ANCOVA tradicional supone que la pendiente de la covariable es común en todos los grupos. Este supuesto puede expresarse como ausencia de interacción entre el factor y la covariable.
Modelo de pendientes homogéneas:
\[ Y=\beta_0+\beta_1D+\beta_2X+\varepsilon. \]
Modelo de pendientes heterogéneas:
\[ Y=\beta_0+\beta_1D+\beta_2X+\beta_3DX+\varepsilon. \]
modelo_homogeneo <- lm(
costo_siniestros ~
zona +
valor_c +
km_c +
edad_c,
data = polizas
)
modelo_heterogeneo <- lm(
costo_siniestros ~
zona * km_c +
valor_c +
edad_c,
data = polizas
)
anova(modelo_homogeneo, modelo_heterogeneo)Si la interacción es relevante, la diferencia entre zonas depende del kilometraje. En ese caso no existe una única diferencia de zona válida para todos los niveles de la covariable.
En un modelo con zona * km_c, R incluye:
zona,km_c,zona:km_c.Los efectos principales se interpretan cuando la otra variable vale cero. Debido al centrado, cero corresponde al kilometraje promedio.
knitr::kable(
tabla_coeficientes(modelo_heterogeneo),
caption = "Modelo con pendientes diferentes por zona"
)| Término | Estimación | Error estándar | Estadístico t | Valor p |
|---|---|---|---|---|
| (Intercept) | 3252.6906 | 82.5858 | 39.3856 | 0.0000 |
| zonaMedia | 267.8050 | 120.9811 | 2.2136 | 0.0279 |
| zonaAlta | 996.5458 | 126.7289 | 7.8636 | 0.0000 |
| km_c | 30.6309 | 9.1391 | 3.3516 | 0.0010 |
| valor_c | 213.8184 | 10.7829 | 19.8294 | 0.0000 |
| edad_c | -3.8724 | 3.5189 | -1.1004 | 0.2724 |
| zonaMedia:km_c | -4.0299 | 13.4448 | -0.2997 | 0.7647 |
| zonaAlta:km_c | 16.9471 | 15.2905 | 1.1083 | 0.2690 |
rejilla <- expand.grid(
km_c = seq(
min(polizas$km_c),
max(polizas$km_c),
length.out = 80
),
zona = factor(
levels(polizas$zona),
levels = levels(polizas$zona)
),
valor_c = 0,
edad_c = 0
)
rejilla$prediccion <- predict(
modelo_heterogeneo,
newdata = rejilla
)
limites_y <- range(
polizas$costo_siniestros,
rejilla$prediccion
)
plot(
NA,
xlim = range(polizas$km_c),
ylim = limites_y,
xlab = "Kilometraje centrado, miles",
ylab = "Costo anual de siniestros",
main = "Pendientes estimadas por zona"
)
for (nivel in levels(polizas$zona)) {
datos_nivel <- rejilla[rejilla$zona == nivel, ]
lines(
datos_nivel$km_c,
datos_nivel$prediccion,
lwd = 2,
lty = which(levels(polizas$zona) == nivel)
)
}
legend(
"topleft",
legend = levels(polizas$zona),
lty = seq_along(levels(polizas$zona)),
lwd = 2,
bty = "n"
)Comprobación 4. En el modelo con interacción, ¿qué
representa el coeficiente de zonaAlta:km_c?
Representa cuánto difiere la pendiente del kilometraje en la zona
alta respecto de la pendiente de la zona de referencia, que es la zona
baja. La pendiente para la zona alta se obtiene sumando el coeficiente
de km_c y el coeficiente de zonaAlta:km_c.
La multicolinealidad aparece cuando un predictor puede explicarse de forma importante mediante otros predictores.
Consecuencias posibles:
La multicolinealidad no implica necesariamente malas predicciones dentro del rango observado, pero sí limita la interpretación individual de los coeficientes.
## [1] 0.9820489
modelo_colineal <- lm(
costo_siniestros ~
valor_vehiculo_10k +
kilometraje_1000 +
edad +
experiencia,
data = polizas
)
summary(modelo_colineal)##
## Call:
## lm(formula = costo_siniestros ~ valor_vehiculo_10k + kilometraje_1000 +
## edad + experiencia, data = polizas)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2665.44 -569.13 6.02 560.03 2355.65
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 986.504 455.092 2.168 0.0313 *
## valor_vehiculo_10k 220.726 12.195 18.099 < 0.0000000000000002 ***
## kilometraje_1000 32.809 6.682 4.910 0.0000018 ***
## edad -9.027 20.986 -0.430 0.6675
## experiencia 7.872 20.880 0.377 0.7065
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 856.6 on 215 degrees of freedom
## Multiple R-squared: 0.6228, Adjusted R-squared: 0.6158
## F-statistic: 88.75 on 4 and 215 DF, p-value: < 0.00000000000000022
Para el predictor \(X_j\):
\[ VIF_j=\frac{1}{1-R_j^2}, \]
donde \(R_j^2\) proviene de predecir \(X_j\) con los demás predictores.
vif_manual <- function(modelo) {
X <- model.matrix(modelo)
# Se elimina el intercepto, si existe.
if ("(Intercept)" %in% colnames(X)) {
X <- X[, colnames(X) != "(Intercept)", drop = FALSE]
}
if (ncol(X) < 2) {
stop("Se necesitan al menos dos columnas predictoras.")
}
resultado <- numeric(ncol(X))
names(resultado) <- colnames(X)
for (j in seq_len(ncol(X))) {
respuesta <- X[, j]
predictores <- X[, -j, drop = FALSE]
modelo_auxiliar <- lm(respuesta ~ predictores)
R2_j <- summary(modelo_auxiliar)$r.squared
resultado[j] <- 1 / (1 - R2_j)
}
resultado
}
round(vif_manual(modelo_colineal), 3)## valor_vehiculo_10k kilometraje_1000 edad experiencia
## 1.006 1.004 28.174 28.198
Reglas como VIF mayor que 5 o 10 son señales orientativas, no leyes universales. Debe examinarse el contexto, la precisión requerida y la función del predictor.
## (Intercept) valor_vehiculo_10k kilometraje_1000 edad experiencia
## 986.503868 220.726036 32.809378 -9.026702 7.872147
## (Intercept) valor_vehiculo_10k kilometraje_1000 edad
## 845.557029 220.464138 32.795431 -1.257063
Posibles decisiones: conservar ambos predictores por razones teóricas, eliminar uno redundante, combinarlos, redefinir el objetivo inferencial, aumentar información muestral o utilizar regularización cuando el objetivo principal sea predictivo.
Para inferencia clásica por mínimos cuadrados se revisan los siguientes supuestos.
\[ E(Y\mid X)=X\beta. \]
La forma funcional debe representar razonablemente la media condicional. La falta de linealidad puede requerir transformaciones, términos polinómicos o interacciones.
\[ E(\varepsilon\mid X)=0. \]
Este supuesto implica que el error no contiene un patrón sistemático relacionado con los predictores. Puede violarse por variables omitidas, simultaneidad, errores de medición o selección de muestra.
\[ Var(\varepsilon_i\mid X)=\sigma^2. \]
La heterocedasticidad altera los errores estándar clásicos, aunque los coeficientes OLS pueden continuar siendo insesgados bajo otros supuestos.
Los errores no deben presentar dependencia no modelada. La independencia depende principalmente del diseño de recolección. Datos longitudinales, agrupados o temporales requieren estructuras específicas.
La normalidad es importante para inferencia exacta en muestras pequeñas. No es necesaria para que mínimos cuadrados defina la recta o superficie que minimiza la suma de cuadrados.
Ninguna columna de la matriz de diseño debe ser una combinación lineal exacta de otras columnas.
Los diagnósticos no “demuestran” que los supuestos sean verdaderos. Permiten identificar patrones incompatibles con ellos y evaluar la sensibilidad de las conclusiones.
Se utilizará el modelo con factores como modelo principal.
La prueba de Breusch-Pagan puede implementarse mediante una regresión auxiliar de los residuales cuadrados.
breusch_pagan_manual <- function(modelo) {
e2 <- residuals(modelo)^2
X <- model.matrix(modelo)
modelo_auxiliar <- lm(e2 ~ X[, -1, drop = FALSE])
LM <- length(e2) * summary(modelo_auxiliar)$r.squared
gl <- ncol(X) - 1
valor_p <- pchisq(LM, df = gl, lower.tail = FALSE)
data.frame(
estadistico_LM = LM,
grados_libertad = gl,
valor_p = valor_p
)
}
breusch_pagan_manual(modelo_diagnostico)No debe utilizarse una prueba de supuestos como un interruptor mecánico de “válido/no válido”. Examine también magnitud, gráficos y consecuencias prácticas.
Los residuales estudentizados eliminados recalculan la estimación de la variabilidad dejando fuera temporalmente la observación evaluada.
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -3.68952 -0.66002 -0.01775 -0.00022 0.55182 2.61214
## 25 39 76 79 107 111 120 161 172 200 205 215
## 25 39 76 79 107 111 120 161 172 200 205 215
El umbral de 2 es una regla inicial. Cuando se examinan muchas observaciones, conviene considerar ajustes por multiplicidad y revisar el contexto.
El leverage \(h_{ii}\) mide qué tan inusual es la combinación de valores predictores de una observación.
h <- hatvalues(modelo_diagnostico)
p_parametros <- length(coef(modelo_diagnostico))
n_observaciones <- nobs(modelo_diagnostico)
umbral_h_2 <- 2 * p_parametros / n_observaciones
umbral_h_3 <- 3 * p_parametros / n_observaciones
c(
umbral_dos = umbral_h_2,
umbral_tres = umbral_h_3
)## umbral_dos umbral_tres
## 0.07272727 0.10909091
## 201
## 201
La distancia de Cook resume cuánto podrían cambiar los valores ajustados al eliminar una observación.
## 21 25 79 107 109 120 161 172 200 201 215
## 21 25 79 107 109 120 161 172 200 201 215
plot(
D,
type = "h",
xlab = "Observación",
ylab = "Distancia de Cook",
main = "Influencia de las observaciones"
)
abline(h = umbral_cook, lty = 2)diagnostico_observaciones <- data.frame(
observacion = seq_len(n_observaciones),
residual = residuals(modelo_diagnostico),
residual_estudentizado = rstudent_valores,
leverage = h,
cook = D
)
diagnostico_observaciones <- diagnostico_observaciones[
order(diagnostico_observaciones$cook, decreasing = TRUE),
]
knitr::kable(
head(diagnostico_observaciones, 10),
digits = 4,
caption = "Diez observaciones con mayor distancia de Cook"
)| observacion | residual | residual_estudentizado | leverage | cook | |
|---|---|---|---|---|---|
| 215 | 215 | -2517.5822 | -3.6895 | 0.0580 | 0.0989 |
| 107 | 107 | -2465.4706 | -3.5744 | 0.0411 | 0.0648 |
| 200 | 200 | -1912.7390 | -2.7460 | 0.0450 | 0.0431 |
| 21 | 21 | 1370.6822 | 1.9685 | 0.0617 | 0.0314 |
| 161 | 161 | 1678.9582 | 2.3974 | 0.0425 | 0.0312 |
| 120 | 120 | 1693.7403 | 2.4139 | 0.0385 | 0.0285 |
| 172 | 172 | 1834.3373 | 2.6121 | 0.0325 | 0.0279 |
| 201 | 201 | 855.8091 | 1.2570 | 0.1125 | 0.0250 |
| 79 | 79 | -1428.9433 | -2.0355 | 0.0450 | 0.0240 |
| 25 | 25 | -1415.7209 | -2.0127 | 0.0417 | 0.0217 |
Una observación influyente no debe eliminarse automáticamente. Primero verifique errores de registro, pertenencia a la población, mecanismo de generación y sensibilidad de las conclusiones con y sin la observación.
Para una combinación de predictores \(x_0\), pueden construirse dos intervalos diferentes.
Estima:
\[ E(Y\mid X=x_0). \]
Estima un nuevo valor individual:
\[ Y_{\text{nuevo}}\mid X=x_0. \]
El intervalo de predicción es más amplio porque incluye:
nueva_poliza <- data.frame(
valor_c = 12 - mean(polizas$valor_vehiculo_10k),
km_c = 18 - mean(polizas$kilometraje_1000),
edad_c = 35 - mean(polizas$edad),
zona = factor("Media", levels = levels(polizas$zona)),
tipo_vehiculo = factor(
"SUV",
levels = levels(polizas$tipo_vehiculo)
)
)
IC_media <- predict(
modelo_diagnostico,
newdata = nueva_poliza,
interval = "confidence",
level = 0.95
)
IP_individual <- predict(
modelo_diagnostico,
newdata = nueva_poliza,
interval = "prediction",
level = 0.95
)
IC_media## fit lwr upr
## 1 4178.718 3920.964 4436.473
## fit lwr upr
## 1 4178.718 2729.104 5628.333
Comprobación 5. ¿Cuál intervalo debe reportarse para estimar el costo promedio de todas las pólizas con ese perfil y cuál para anticipar el costo de una nueva póliza individual?
Para el costo promedio se utiliza el intervalo de confianza de la respuesta media. Para una nueva póliza individual se utiliza el intervalo de predicción.
La inferencia busca comprender parámetros, efectos ajustados e incertidumbre. La predicción busca desempeño sobre datos no utilizados en el ajuste.
Un modelo puede:
set.seed(1517)
indice_entrenamiento <- sample(
seq_len(nrow(polizas)),
size = floor(0.75 * nrow(polizas))
)
entrenamiento <- polizas[indice_entrenamiento, ]
prueba <- polizas[-indice_entrenamiento, ]
modelo_entrenamiento <- lm(
costo_siniestros ~
valor_vehiculo_10k +
kilometraje_1000 +
edad +
zona +
tipo_vehiculo,
data = entrenamiento
)
pred_prueba <- predict(
modelo_entrenamiento,
newdata = prueba
)
RMSE <- sqrt(
mean((prueba$costo_siniestros - pred_prueba)^2)
)
MAE <- mean(
abs(prueba$costo_siniestros - pred_prueba)
)
c(RMSE = RMSE, MAE = MAE)## RMSE MAE
## 728.8596 567.8174
SSE_prueba <- sum(
(prueba$costo_siniestros - pred_prueba)^2
)
SST_prueba <- sum(
(
prueba$costo_siniestros -
mean(entrenamiento$costo_siniestros)
)^2
)
R2_prueba <- 1 - SSE_prueba / SST_prueba
R2_prueba## [1] 0.5932393
La evaluación predictiva debe usar datos nuevos, validación cruzada o remuestreo. El \(R^2\) de entrenamiento es una medida de ajuste, no una garantía de generalización.
Los coeficientes no estandarizados dependen de las unidades. Para comparar asociaciones en escalas distintas puede estimarse un modelo con variables estandarizadas:
\[ Z=\frac{X-\overline{X}}{s_X}. \]
datos_estandarizados <- data.frame(
costo_z = as.numeric(scale(polizas$costo_siniestros)),
valor_z = as.numeric(scale(polizas$valor_vehiculo_10k)),
km_z = as.numeric(scale(polizas$kilometraje_1000)),
edad_z = as.numeric(scale(polizas$edad))
)
modelo_estandarizado <- lm(
costo_z ~ valor_z + km_z + edad_z,
data = datos_estandarizados
)
coef(modelo_estandarizado)## (Intercept) valor_z km_z edad_z
## -0.000000000000000227079 0.759522869720220650258 0.206028106100576036130 -0.013317297462060586483
Un coeficiente estandarizado indica el cambio esperado en desviaciones estándar de \(Y\) por un aumento de una desviación estándar en el predictor, manteniendo los otros constantes.
Los coeficientes estandarizados no sustituyen la interpretación en unidades originales y no resuelven multicolinealidad, confusión ni problemas de diseño.
Una estrategia disciplinada:
Anderson, D. R., Sweeney, D. J. y Williams, T. A. Estadística para negocios y economía, 11.ª edición. Capítulo 15, Regresión múltiple.
Rutherford, A. ANOVA and ANCOVA: A GLM Approach, 2.ª edición. Secciones sobre Modelo Lineal General, comparación de modelos completos y reducidos, codificación de condiciones experimentales, ANCOVA, supuestos y regresiones heterogéneas.
El material presenta una síntesis didáctica original y utiliza un caso simulado para fines docentes.