10.3 Introducción a los modelos logístico multinivel.
Los modelos logísticos multinivel son una extensión de los modelos logísticos simples, que se utilizan para predecir la probabilidad de un resultado binario en función de una o varias variables explicativas. Sin embargo, en muchas situaciones, los datos se recogen de individuos que están agrupados en diferentes niveles o unidades de análisis, como escuelas, ciudades o países. En estos casos, los modelos logísticos simples pueden no ser suficientes para capturar la estructura jerárquica de los datos y la variación en las respuestas entre los diferentes grupos.
Los modelos logísticos multinivel resuelven este problema al permitir que los coeficientes del modelo varíen a través de los diferentes niveles de análisis. En otras palabras, se permite que la relación entre las variables predictoras y la respuesta varíe en función del grupo al que pertenece cada individuo.
Además, los modelos logísticos multinivel permiten incluir tanto variables a nivel individual como variables a nivel de grupo, lo que aumenta la precisión de las estimaciones y la capacidad de explicar la variabilidad en las respuestas. También permiten estimar la varianza en las respuestas entre los diferentes grupos, lo que es útil para identificar las fuentes de variabilidad y para comparar la variabilidad entre grupos.
En general, los modelos logísticos multinivel son una herramienta poderosa para analizar datos de respuestas binarias en contextos jerárquicos, y son ampliamente utilizados en muchas áreas de investigación, como la educación, la salud, las ciencias sociales y la psicología.
Sea la variable \(y_{ij} = 1\) si el individuo \(i\) en el estrato \(j\) está por encima de la línea de pobreza y \(y_{ij} = 0\) en caso contrario, la variable \(y_{ij}\) se puede modelar mediante el modelo logístico:
\[ Pr\left(y_{ij}\right)=Pr\left(y_{ij}=1\mid x_{i}:\boldsymbol{\beta}\right)=\frac{1}{1+\exp\left(\boldsymbol{-\beta}_{j}\boldsymbol{x}_{ij}\right)} \]
ó
\[ \log\left(\frac{\pi_{ij}}{1-\pi_{ij}}\right)=\boldsymbol{\beta}_{j}\boldsymbol{x}_{ij} \]
donde,
\[ \pi_{ij}=Pr\left(y_{ij}=1\mid x_{i}:\boldsymbol{\beta}\right) \].
A modo de ejemplo, se ajustará un modelo logístico para la variable pobreza. Inicialmente, se crea la variable dicotómica en la base como se muestra a continuación:
<- encuesta %>%
encuesta_plot ::select(Stratum,Expenditure) %>% unique() %>%
dplyrgroup_by(Stratum) %>%
summarise(sd = sd(Expenditure)) %>%
arrange(desc(sd)) %>% dplyr::select(-sd) %>%
slice(1:20L) %>%
inner_join(encuesta) %>%
::select(Poverty, Expenditure, Stratum,
dplyr
Sex, Region, Zone) %>% slice(1:15L) encuesta_plot
Poverty | Expenditure | Stratum | Sex | Region | Zone |
---|---|---|---|---|---|
NotPoor | 3367.53 | idStrt039 | Male | Sur | Urban |
NotPoor | 3367.53 | idStrt039 | Female | Sur | Urban |
NotPoor | 3367.53 | idStrt039 | Male | Sur | Urban |
NotPoor | 312.13 | idStrt039 | Female | Sur | Urban |
NotPoor | 312.13 | idStrt039 | Female | Sur | Urban |
NotPoor | 312.13 | idStrt039 | Female | Sur | Urban |
NotPoor | 312.13 | idStrt039 | Male | Sur | Urban |
NotPoor | 226.50 | idStrt039 | Male | Sur | Urban |
NotPoor | 226.50 | idStrt039 | Female | Sur | Urban |
NotPoor | 616.32 | idStrt047 | Female | Sur | Urban |
NotPoor | 616.32 | idStrt047 | Female | Sur | Urban |
NotPoor | 616.32 | idStrt047 | Female | Sur | Urban |
NotPoor | 1385.65 | idStrt047 | Male | Sur | Urban |
NotPoor | 1385.65 | idStrt047 | Female | Sur | Urban |
NotPoor | 1385.65 | idStrt047 | Female | Sur | Urban |
Para poder observar la distribución la distribución de la variable pobreza, se presenta el siguiente gráfico:
<- encuesta %>% mutate( pobreza = ifelse(Poverty != "NotPoor", 1, 0))
encuesta %<>% mutate(pobreza = ifelse(Poverty != "NotPoor", 1, 0))
encuesta_plot
ggplot(data = encuesta, aes(y = pobreza, x = Expenditure)) +
geom_point() + geom_smooth(formula = y~x, method = "glm",se=FALSE,
method.args = list(family=binomial(link = "logit"))) + theme_bw()
El ajuste del modelo logístico se realiza con la función
glm
y la función link “logit”. Una vez se ajusta el modelo, se extraen los coeficientes del modelo y así poder calcular las probabilidades, como sigue a continuación:
<- function(x,b0,b1){
auxLogit 1/(1+exp(-(b0+b1*x)))
}
= coef(glm(pobreza~1,data = encuesta_plot,
B0 family=binomial(link = "logit")))
<- encuesta_plot %>% group_by(Stratum) %>%
(coef_Mod summarise(B1 = coef(glm(pobreza ~ -1 + Expenditure,
family=binomial(link = "logit")))) %>%
mutate(B0 = B0)) %>% slice(1:6L)
Stratum | B1 | B0 |
---|---|---|
idStrt007 | -0.0189122 | -0.8781751 |
idStrt020 | -0.0009882 | -0.8781751 |
idStrt022 | -0.0057026 | -0.8781751 |
idStrt024 | -0.0020174 | -0.8781751 |
idStrt036 | -0.0008913 | -0.8781751 |
idStrt039 | -0.0976218 | -0.8781751 |
A continuación, se grafican los diferentes modelos logísticos ajustados para cada uno de los estratos observándose que, hay una variación importante entre los estratos:
<- coef_Mod %>% mutate(Expenditure = list(seq(0,2000, length =100))) %>%
pred_logit ::unnest_legacy()
tidyr
%<>% mutate(Prob = auxLogit(Expenditure,B0,B1))
pred_logit
ggplot(data = pred_logit, aes(y = Prob, x = Expenditure, colour = Stratum)) +
geom_line() + theme_bw() + theme(legend.position = "none")
Un modelo logístico básico o nulo se escribe de la siguiente manera:
\[ logit( \pi_{ij})=\beta_{0j}+\epsilon_{ij} \]
\[ \beta_{0j}=\gamma_{00}+\tau_{0j} \] Donde los componentes son los siguientes:
- \(\pi_{ij}=Pr\left(y_{ij}=1\mid x_{i}:\boldsymbol{\beta}\right)\).
- \(\beta_{0j}=\) El intercepto en el estrato \(j\).
- \(\epsilon_{ij}\) El residual de la persona \(i\) en el estrato \(j\).
- \(\gamma_{00}=\) El intercepto en general.
- \(\tau_{0j}=\) Efecto aleatorio para el intercepto.
con, \(\tau_{0j}\sim N\left(0,\sigma_{\tau}^{2}\right)\) y \(\epsilon_{ij}\sim N\left(0,\sigma_{\epsilon}^{2}\right)\).
En este caso, la correlación intra clásica está dada por:
\[
\rho=\frac{\sigma_{\tau}^{2}}{\sigma_{\tau}^{2}+\sigma_{\epsilon}^{2}}
\]
En R
el modelo nulo se ajusta de la siguiente manera:
library(lme4)
<- glmer( pobreza ~ ( 1 | Stratum ),
mod_logist_null data = encuesta,
weights = wk2,
family = binomial(link = "logit") )
coef( mod_logist_null )$Stratum %>% slice(1:12)
(Intercept) | |
---|---|
idStrt001 | -0.8333883 |
idStrt002 | -0.0133038 |
idStrt003 | -2.6022877 |
idStrt004 | -2.7770188 |
idStrt005 | -1.0267951 |
idStrt006 | 1.0100380 |
idStrt007 | -1.0133900 |
idStrt008 | 0.2035036 |
idStrt009 | 2.1965550 |
idStrt010 | -0.5948075 |
idStrt011 | -1.2985509 |
idStrt012 | 0.2824748 |
Las estadísticas resumen del modelo se presentan a continuación:
library(sjstats)
mod_logist_null
## Generalized linear mixed model fit by maximum likelihood (Laplace
## Approximation) [glmerMod]
## Family: binomial ( logit )
## Formula: pobreza ~ (1 | Stratum)
## Data: encuesta
## Weights: wk2
## AIC BIC logLik deviance df.resid
## 2966.056 2977.786 -1481.028 2962.056 2603
## Random effects:
## Groups Name Std.Dev.
## Stratum (Intercept) 1.285
## Number of obs: 2605, groups: Stratum, 119
## Fixed Effects:
## (Intercept)
## -0.8015
A continuación, se presenta la correlación intraclase, las predicciones del modelo y las variables observadas:
::icc(mod_logist_null) performance
ICC_adjusted | ICC_unadjusted | optional |
---|---|---|
0.3341999 | 0.3341999 | FALSE |
<- data.frame(Pred = predict(mod_logist_null, type = "response"),
(tab_pred pobreza = encuesta$pobreza,
Stratum = encuesta$Stratum)) %>% distinct() %>%
slice(1:6L) # Son las pendientes aleatorias
Pred | pobreza | Stratum | |
---|---|---|---|
1 | 0.3029291 | 0 | idStrt001 |
10 | 0.3029291 | 1 | idStrt001 |
28 | 0.4966741 | 1 | idStrt002 |
36 | 0.4966741 | 0 | idStrt002 |
61 | 0.0689913 | 0 | idStrt003 |
84 | 0.0585787 | 0 | idStrt004 |
Para efecto de verificar qué tan buena fueron las predicciones del modelo, se estiman el porcentaje de pobreza de la variable observada y de las predicciones de modelo utilizando la función weighted.mean
. Se logra observar que son muy similares las estimaciones:
weighted.mean(encuesta$pobreza, encuesta$wk2)
## [1] 0.3858509
weighted.mean(tab_pred$Pred, encuesta$wk2)
## [1] 0.3850068
Modelo con intercepto aleatoria
EL modelo se define de la siguiente manera:
\[ logit(\pi_{ij})=\beta_{0}+\beta_{1j}Gasto_{ij}+\epsilon_{ij} \] Donde,
\[
\beta_{1j} = \gamma_{10}+\gamma_{11}Stratum_{j} + \tau_{1j}
\]
Siguiendo las ideas de la sección anterior, el ajuste del modelo en R
se realiza de la siguiente manera:
<- glmer(pobreza ~ Expenditure + (1 | Stratum),
mod_logit_Int_Aleatorio data = encuesta, family = binomial(link = "logit"),weights = wk2)
::icc(mod_logit_Int_Aleatorio) performance
ICC_adjusted | ICC_unadjusted | optional |
---|---|---|
0.3151349 | 0.1867082 | FALSE |
Los coeficientes estimados son:
coef(mod_logit_Int_Aleatorio)$Stratum %>% slice(1:10L)
(Intercept) | Expenditure | |
---|---|---|
idStrt001 | 0.9888770 | -0.0065962 |
idStrt002 | 1.8836801 | -0.0065962 |
idStrt003 | -0.7462533 | -0.0065962 |
idStrt004 | -0.1484101 | -0.0065962 |
idStrt005 | 1.7154836 | -0.0065962 |
idStrt006 | 3.2456075 | -0.0065962 |
idStrt007 | 0.5600832 | -0.0065962 |
idStrt008 | 1.6847527 | -0.0065962 |
idStrt009 | 3.9332398 | -0.0065962 |
idStrt010 | 1.1206950 | -0.0065962 |
Gráficamente, los modelos ajustados se muestran a continuación:
<- encuesta %>% group_by(Stratum) %>%
dat_pred summarise(Expenditure = list(seq(min(Expenditure),
max(Expenditure), len = 100))) %>% tidyr::unnest_legacy()
<- mutate(dat_pred,Proba = predict(mod_logit_Int_Aleatorio,
dat_pred newdata = dat_pred , type = "response"))
ggplot(data = dat_pred,
aes(y = Proba, x = Expenditure,
colour = Stratum)) +
geom_line()+ theme_bw() +
geom_point(data = encuesta, aes(y = pobreza, x = Expenditure))+
theme(legend.position = "none",
plot.title = element_text(hjust = 0.5))
Las predicciones del modelo se presentan a continuación:
<- data.frame(Pred = predict(mod_logit_Int_Aleatorio,
(tab_pred type = "response"),
pobreza = encuesta$pobreza,
Stratum = encuesta$Stratum,
wk2 = encuesta$wk2)) %>% distinct() %>%
slice(1:6L)
Pred | pobreza | Stratum | wk2 |
---|---|---|---|
0.2148957 | 0 | idStrt001 | 0.7769795 |
0.2148957 | 0 | idStrt001 | 0.7501360 |
0.2148957 | 0 | idStrt001 | 0.7463022 |
0.2148957 | 0 | idStrt001 | 0.7717254 |
0.2148957 | 0 | idStrt001 | 0.7438076 |
0.1682010 | 0 | idStrt001 | 0.7507385 |
Como se indicó anteriormente, para verificar la calidad del modelo se realizan las estimaciones de las predicciones y de las variables observadas, teniendo estimaciones similares:
%>%
tab_pred summarise(Pred = weighted.mean(Pred, wk2),
pobreza = weighted.mean(pobreza,wk2))
Pred | pobreza |
---|---|
0.3855031 | 0.3858509 |
Modelo con intercepto y pendiente aleatoria
Los modelos logísticos con intercepto y pendiente aleatoria son un tipo de modelo logístico multinivel que permiten que tanto el intercepto como la pendiente varíen aleatoriamente entre los diferentes grupos de observación.
En los modelos logísticos básicos, la relación entre las variables predictoras y la variable de respuesta se modela mediante una función logística, donde la respuesta es la probabilidad de que el resultado binario ocurra. En los modelos con intercepto y pendiente aleatoria, la función logística se ajusta para cada grupo de observación, y tanto el intercepto como la pendiente son variables aleatorias que varían de un grupo a otro. Esto permite que los coeficientes del modelo, que representan la relación entre las variables predictoras y la respuesta, varíen según el grupo de observación.
La incorporación de coeficientes aleatorios en los modelos logísticos multinivel permite capturar la heterogeneidad en la relación entre las variables predictoras y la respuesta en diferentes grupos de observación, y mejora la precisión de las estimaciones. Además, estos modelos también permiten la inclusión de variables a nivel individual y a nivel de grupo, lo que permite una mejor comprensión de la estructura jerárquica de los datos. El modelo se define de la siguiente manera:
\[ logit(\pi_{ij})=\beta_{0j}+\beta_{1j}Gasto_{ij}+\epsilon_{ij} \]
con,
\[ \beta_{0j} = \gamma_{00}+\gamma_{01}Stratum_{j} + \tau_{0j} \]
donde,
\[ \beta_{1j} = \gamma_{10}+\gamma_{11}Stratum_{j} + \tau_{1j} \]
En R
, el ajuste se hace de la siguiente manera:
<- glmer(pobreza ~ Expenditure + (1 + Expenditure| Stratum),
mod_logit_Pen_Aleatorio data = encuesta, weights = wk2, binomial(link = "logit"))
::icc(mod_logit_Pen_Aleatorio) performance
ICC_adjusted | ICC_unadjusted | optional |
---|---|---|
0.8858594 | 0.6533971 | FALSE |
Los coeficientes del modelo son:
coef(mod_logit_Pen_Aleatorio)$Stratum %>% slice(1:10L)
(Intercept) | Expenditure | |
---|---|---|
idStrt001 | 5.244003 | -0.0271496 |
idStrt002 | 11.058446 | -0.0394091 |
idStrt003 | -1.614168 | -0.0059837 |
idStrt004 | 1.654808 | -0.0152715 |
idStrt005 | 9.055225 | -0.0289090 |
idStrt006 | -1.354381 | 0.0100316 |
idStrt007 | 1.034633 | -0.0135859 |
idStrt008 | 1.472601 | -0.0055526 |
idStrt009 | 4.049805 | -0.0048253 |
idStrt010 | 4.310186 | -0.0214105 |
Gráficamente el ajuste de los modelo se muestra a continuación:
<- encuesta %>% group_by(Stratum) %>%
dat_pred summarise(Expenditure = list(seq(min(Expenditure), max(Expenditure), len = 100))) %>%
::unnest_legacy()
tidyr
<- mutate(dat_pred,Proba = predict(mod_logit_Pen_Aleatorio, newdata = dat_pred , type = "response"))
dat_pred
ggplot(data = dat_pred,
aes(y = Proba, x = Expenditure,
colour = Stratum)) +
geom_line()+ theme_bw() +
geom_point(data = encuesta, aes(y = pobreza, x = Expenditure))+
theme(legend.position = "none",
plot.title = element_text(hjust = 0.5))
Las predicciones se muestran a continuación:
<- data.frame(
(tab_pred Pred = predict(mod_logit_Pen_Aleatorio,
type = "response"),
pobreza = encuesta$pobreza,
Stratum = encuesta$Stratum,
wk2 = encuesta$wk2)) %>% distinct() %>%
slice(1:6L)
Pred | pobreza | Stratum | wk2 |
---|---|---|---|
0.0153830 | 0 | idStrt001 | 0.7769795 |
0.0153830 | 0 | idStrt001 | 0.7501360 |
0.0153830 | 0 | idStrt001 | 0.7463022 |
0.0153830 | 0 | idStrt001 | 0.7717254 |
0.0153830 | 0 | idStrt001 | 0.7438076 |
0.0044732 | 0 | idStrt001 | 0.7507385 |
La calidad de la predicción del modelo es muy buena como se muestra a continuación:
%>%
tab_pred summarise(Pred = weighted.mean(Pred, wk2),
pobreza = weighted.mean(pobreza,wk2))
Pred | pobreza |
---|---|
0.3845282 | 0.3858509 |
Por otro lado, se ajusta un modelo agregando ahora la variable zona. La idea es entonces medir el porcentaje de pobreza discriminando por zona. El modelo es el siguiente:
\[ logit(\pi_{ij})=\beta_{0j}+\beta_{1j}Gasto_{ij}+\beta_{2j}Zona_{ij} +\epsilon_{ij} \] Donde, \[ \beta_{0j} = \gamma_{00}+\gamma_{01}Stratum_{j} + \gamma_{02}\mu_{j} + \tau_{0j} \] con,
\[ \beta_{1j} = \gamma_{10}+\gamma_{11}Stratum_{j} + \gamma_{12}\mu_{j} + \tau_{1j} \] y,
\[ \beta_{2j} = \gamma_{20}+\gamma_{21}Stratum_{j} + \gamma_{12}\mu_{j} + \tau_{2j} \]
donde \(\mu_{j}\) es el gasto medio en el estrato \(j\).
El ajuste del modelo es el siguiente:
<- glmer(
mod_logit_Pen_Aleatorio2 ~ 1 + Expenditure + Zone + mu +
pobreza 1 + Expenditure + Zone + mu | Stratum ),
(data = encuesta, weights = wk2,
binomial(link = "logit"))
::icc(mod_logit_Pen_Aleatorio2) performance
ICC_adjusted | ICC_unadjusted | optional |
---|---|---|
0.9479436 | 0.5534188 | FALSE |
Se grafican los modelos ajustados anteriormente:
<- encuesta %>% group_by(Stratum, Zone, mu) %>%
dat_pred summarise(
Expenditure = list(seq(min(Expenditure),
max(Expenditure), len = 100))) %>%
::unnest_legacy()
tidyr
$Proba = predict(mod_logit_Pen_Aleatorio2,
dat_prednewdata = dat_pred , type = "response")
ggplot(data = dat_pred,
aes(y = Proba, x = Expenditure,
colour = Stratum)) +
geom_line()+ theme_bw() +facet_grid(.~Zone)+
geom_point(data = encuesta, aes(y = pobreza, x = Expenditure))+
theme(legend.position = "none",
plot.title = element_text(hjust = 0.5))
Se logra observar que, hay una variación importante en el ajuste de los modelos para cada zona. Ahora bien, las predicciones del porcentaje de pobreza por zona se calculan a continuación:
<- data.frame(
(tab_pred Pred = predict(mod_logit_Pen_Aleatorio2,
type = "response"),
pobreza = encuesta$pobreza,
Stratum = encuesta$Stratum,
Zone = encuesta$Zone,
wk2 = encuesta$wk2)) %>% distinct() %>%
slice(1:6L)
Pred | pobreza | Stratum | Zone | wk2 |
---|---|---|---|---|
0.0046039 | 0 | idStrt001 | Rural | 0.7769795 |
0.0046039 | 0 | idStrt001 | Rural | 0.7501360 |
0.0046039 | 0 | idStrt001 | Rural | 0.7463022 |
0.0046039 | 0 | idStrt001 | Rural | 0.7717254 |
0.0046039 | 0 | idStrt001 | Rural | 0.7438076 |
0.0009514 | 0 | idStrt001 | Rural | 0.7507385 |
Por último, se verifica la calidad de las predicciones, obteniendo, como en los modelos anteriores, unas predicciones de buena calidad haciendo las comparaciones con las estimaciones de la variable observada para cada una de las zonas.
%>% group_by(Zone) %>%
tab_pred summarise(Pred = weighted.mean(Pred, wk2),
pobreza = weighted.mean(pobreza,wk2))
Zone | Pred | pobreza |
---|---|---|
Rural | 0.4385635 | 0.4298409 |
Urban | 0.3375923 | 0.3437244 |