11.2 Proceso de estimación en R
Para desarrollar la metodología se hace uso de las siguientes librerías.
# Interprete de STAN en R
library(rstan)
library(rstanarm)
# Manejo de bases de datos.
library(tidyverse)
# Gráficas de los modelos.
library(bayesplot)
library(patchwork)
# Organizar la presentación de las tablas
library(kableExtra)
library(printr)
Un conjunto de funciones desarrolladas para realizar de forma simplificada los procesos están consignadas en la siguiente rutina.
source("Recursos/Día4/Sesion1/0Recursos/funciones_mrp.R")
Entre las funciones incluidas en el archivo encuentra
plot_interaction: Esta crea un diagrama de lineas donde se estudia la interacción entre las variables, en el caso de presentar un traslape de las lineas se recomienda incluir el interacción en el modelo.
Plot_Compare Puesto que es necesario realizar una homologar la información del censo y la encuesta es conveniente llevar a cabo una validación de las variables que han sido homologadas, por tanto, se espera que las proporciones resultantes del censo y la encuesta estén cercanas entre sí.
Aux_Agregado: Esta es función permite obtener estimaciones a diferentes niveles de agregación, toma mucha relevancia cuando se realiza un proceso repetitivo.
Las funciones están diseñada específicamente para este proceso
11.2.1 Encuesta de hogares
Los datos empleados en esta ocasión corresponden a la ultima encuesta de hogares, la cual ha sido estandarizada por CEPAL y se encuentra disponible en BADEHOG
<- readRDS("Recursos/Día4/Sesion1/Data/encuestaDOM21N1.rds")
encuesta
<- encuesta %>%
encuesta_mrp transmute(
dam = haven::as_factor(dam_ee,levels = "values"),
dam = str_pad(string = dam, width = 2, pad = "0"),
dam2, ingreso = ingcorte, lp, li,
area = haven::as_factor(area_ee,levels = "values"),
area = case_when(area == 1 ~ "1", TRUE ~ "0"),
logingreso = log(ingcorte + 1),
sexo = as.character(sexo),
anoest = case_when(
< 5 | anoest == -1 | is.na(anoest) ~ "98" , #No aplica
edad == 99 ~ "99", #NS/NR
anoest == 0 ~ "1", # Sin educacion
anoest %in% c(1:6) ~ "2", # 1 - 6
anoest %in% c(7:12) ~ "3", # 7 - 12
anoest > 12 ~ "4", # mas de 12
anoest TRUE ~ "Error" ),
edad = case_when(
< 15 ~ "1",
edad < 30 ~ "2",
edad < 45 ~ "3",
edad < 65 ~ "4",
edad TRUE ~ "5"),
fep = `_fep`
)
tba(encuesta_mrp %>% head(10))
dam | dam2 | ingreso | lp | li | area | logingreso | sexo | anoest | edad | fep |
---|---|---|---|---|---|---|---|---|---|---|
01 | 00101 | 54000.00 | 5622.81 | 3159.09 | 1 | 10.8968 | 1 | 4 | 3 | 137.0652 |
01 | 00101 | 16388.89 | 5622.81 | 3159.09 | 1 | 9.7044 | 2 | 3 | 4 | 137.0652 |
01 | 00101 | 16388.89 | 5622.81 | 3159.09 | 1 | 9.7044 | 1 | 3 | 5 | 137.0652 |
01 | 00101 | 16388.89 | 5622.81 | 3159.09 | 1 | 9.7044 | 1 | 4 | 2 | 137.0652 |
01 | 00101 | 6224.00 | 5622.81 | 3159.09 | 1 | 8.7363 | 2 | 2 | 4 | 137.0652 |
01 | 00101 | 6224.00 | 5622.81 | 3159.09 | 1 | 8.7363 | 1 | 3 | 3 | 137.0652 |
01 | 00101 | 6224.00 | 5622.81 | 3159.09 | 1 | 8.7363 | 2 | 4 | 2 | 137.0652 |
01 | 00101 | 20672.00 | 5622.81 | 3159.09 | 1 | 9.9366 | 2 | 1 | 5 | 137.0652 |
01 | 00101 | 8495.60 | 5622.81 | 3159.09 | 1 | 9.0474 | 1 | 4 | 3 | 137.0652 |
01 | 00101 | 8495.60 | 5622.81 | 3159.09 | 1 | 9.0474 | 2 | 3 | 3 | 137.0652 |
La base de datos de la encuesta tiene la siguientes columnas:
dam: Corresponde al código asignado a la división administrativa mayor del país.
dam2: Corresponde al código asignado a la segunda división administrativa del país.
lp y li lineas de pobreza y pobreza extrema definidas por CEPAL.
área división geográfica (Urbano y Rural).
sexo Hombre y Mujer.
Años de escolaridad (anoest)
Rangos de edad (edad)
Factor de expansión por persona (fep)
Ahora, inspeccionamos el comportamiento de la variable de interés:
<- mean(encuesta_mrp$logingreso)
media <- sd(encuesta_mrp$logingreso)
Sd
ggplot(data = encuesta_mrp, aes(x = logingreso)) +
geom_density(size =2, color = "blue") + labs(y = "") +
stat_function(fun = dnorm,
args = list(mean = media, sd = Sd),
size =2) +
theme_bw(base_size = 20) +
theme(axis.text.y = element_blank(),
axis.ticks = element_blank())
Figura 5.1: Distribuición del ingreso de las personas encuestadas
La información auxiliar disponible ha sido extraída del censo e imágenes satelitales
<-
statelevel_predictors_df readRDS("Recursos/Día4/Sesion1/Data/statelevel_predictors_df_dam2.rds") %>%
mutate_at(.vars = c("luces_nocturnas",
"cubrimiento_cultivo",
"cubrimiento_urbano",
"modificacion_humana",
"accesibilidad_hospitales",
"accesibilidad_hosp_caminado"),
function(x) as.numeric(scale(x)))
tba(statelevel_predictors_df %>% head(10))
dam2 | modificacion_humana | accesibilidad_hospitales | accesibilidad_hosp_caminado | cubrimiento_cultivo | cubrimiento_urbano | luces_nocturnas | area1 | sexo2 | edad2 | edad3 | edad4 | edad5 | anoest2 | anoest3 | anoest4 | anoest99 | tiene_sanitario | tiene_acueducto | tiene_gas | eliminar_basura | tiene_internet | piso_tierra | material_paredes | material_techo | rezago_escolar | alfabeta | hacinamiento | tasa_desocupacion | id_municipio |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
00101 | 3.6127 | -1.1835 | -1.5653 | -1.1560 | 7.2782 | 4.9650 | 1.0000 | 0.5224 | 0.2781 | 0.2117 | 0.1808 | 0.0725 | 0.2000 | 0.3680 | 0.2286 | 0.0193 | 0.0119 | 0.7946 | 0.0673 | 0.0810 | 0.6678 | 0.0033 | 0.0109 | 0.0111 | 0.3694 | 0.9247 | 0.1962 | 0.0066 | 100101 |
00201 | -0.0553 | 0.4449 | 0.2100 | 0.0684 | -0.0682 | -0.1511 | 0.8904 | 0.4933 | 0.2726 | 0.1849 | 0.1520 | 0.0614 | 0.3149 | 0.3022 | 0.0775 | 0.0082 | 0.1005 | 0.7220 | 0.2261 | 0.1300 | 0.9276 | 0.0664 | 0.0812 | 0.0249 | 0.1501 | 0.7975 | 0.3014 | 0.0007 | 050201 |
00202 | -0.3758 | 0.0000 | 0.1482 | -0.2345 | -0.2855 | -0.4234 | 0.6799 | 0.4697 | 0.2804 | 0.1895 | 0.1430 | 0.0515 | 0.3757 | 0.2405 | 0.0148 | 0.0014 | 0.1322 | 0.9230 | 0.2693 | 0.2884 | 0.9759 | 0.0625 | 0.0986 | 0.0673 | 0.0278 | 0.7140 | 0.3454 | 0.0001 | 050202 |
00203 | -0.9259 | 0.5732 | -0.1402 | -0.5511 | -0.3822 | -0.5612 | 0.5814 | 0.4601 | 0.2665 | 0.1733 | 0.1586 | 0.0713 | 0.3778 | 0.2463 | 0.0219 | 0.0052 | 0.2579 | 0.7602 | 0.4824 | 0.2589 | 0.9919 | 0.1937 | 0.2342 | 0.1238 | 0.0485 | 0.7104 | 0.2755 | 0.0001 | 050203 |
00204 | -1.3166 | 1.1111 | 0.4438 | -0.5027 | -0.3835 | -0.6042 | 0.5708 | 0.4663 | 0.2647 | 0.1683 | 0.1673 | 0.0757 | 0.3306 | 0.2402 | 0.0440 | 0.0049 | 0.1672 | 0.6375 | 0.5040 | 0.3837 | 0.9759 | 0.1403 | 0.1354 | 0.0176 | 0.0873 | 0.6737 | 0.2671 | 0.0002 | 050204 |
00205 | -0.7474 | 2.1155 | 1.2271 | -0.5838 | -0.3345 | -0.5909 | 0.6937 | 0.4633 | 0.2849 | 0.2107 | 0.1473 | 0.0583 | 0.2794 | 0.2821 | 0.0562 | 0.0067 | 0.3800 | 0.6596 | 0.5014 | 0.2852 | 0.9894 | 0.2309 | 0.2498 | 0.0459 | 0.1016 | 0.6751 | 0.4973 | 0.0001 | 050205 |
00206 | 0.5157 | -0.1468 | -0.1811 | 1.1894 | -0.1191 | -0.4022 | 0.9563 | 0.4557 | 0.2910 | 0.1814 | 0.1495 | 0.0626 | 0.3793 | 0.2815 | 0.0427 | 0.0052 | 0.1301 | 0.8817 | 0.2565 | 0.1495 | 0.9659 | 0.0629 | 0.0472 | 0.0337 | 0.0835 | 0.8027 | 0.2200 | 0.0001 | 050206 |
00207 | 1.7368 | -0.7648 | -0.4861 | 0.7170 | -0.0609 | 0.0042 | 0.5201 | 0.4783 | 0.2898 | 0.1675 | 0.1464 | 0.0531 | 0.3552 | 0.2901 | 0.0328 | 0.0061 | 0.2434 | 0.5775 | 0.2758 | 0.0950 | 0.9911 | 0.0717 | 0.2004 | 0.1304 | 0.0714 | 0.7778 | 0.3936 | 0.0001 | 050207 |
00208 | -0.5942 | 0.3212 | -0.1697 | -0.3627 | -0.3044 | -0.4750 | 0.6625 | 0.4334 | 0.2943 | 0.1875 | 0.1523 | 0.0654 | 0.3557 | 0.2486 | 0.0250 | 0.0054 | 0.1908 | 0.8251 | 0.4152 | 0.1450 | 0.9907 | 0.1458 | 0.1517 | 0.0852 | 0.0509 | 0.6897 | 0.3051 | 0.0001 | 050208 |
00209 | -1.5280 | 3.0192 | 1.9428 | -0.8078 | -0.4046 | -0.6423 | 0.6798 | 0.4311 | 0.2858 | 0.1687 | 0.1628 | 0.0701 | 0.3648 | 0.2645 | 0.0752 | 0.0061 | 0.1893 | 0.5760 | 0.4096 | 0.3557 | 0.9978 | 0.1097 | 0.0941 | 0.0292 | 0.1357 | 0.7680 | 0.2189 | 0.0001 | 050209 |
11.2.2 Niveles de agregación para colapsar la encuesta
Después de realizar una investigación en la literatura especializada y realizar estudios de simulación fue posible evidenciar que las predicciones obtenidas con la muestra sin agregar y la muestra agregada convergen a la media del dominio. Sin embargo, el realizar estas estimaciones con la muestra agregada reduce el tiempo computacional necesario para la convergencia de las cadenas MCMC. Con esto en mente se se realiza la identificación de las variables por las cuales se agregará la encuesta.
<- c("dam", "dam2", "area",
byAgrega "sexo", "anoest", "edad" )
11.2.3 Creando base con la encuesta agregada
El resultado de agregar la base de dato se muestra a continuación:
<-
encuesta_df_agg %>% # Encuesta
encuesta_mrp group_by_at(all_of(byAgrega)) %>% # Agrupar por el listado de variables
summarise(n = n(), # Número de observaciones
# Ingreso medio de las personas con características similares.
logingreso = mean(logingreso),
.groups = "drop") %>%
arrange(desc(n)) # Ordenar la base.
La tabla obtenida es la siguiente:
dam | dam2 | area | sexo | anoest | edad | n | logingreso |
---|---|---|---|---|---|---|---|
01 | 00101 | 1 | 1 | 3 | 2 | 652 | 9.1000 |
01 | 00101 | 1 | 2 | 3 | 2 | 624 | 8.8678 |
32 | 03201 | 1 | 2 | 3 | 2 | 576 | 8.9571 |
32 | 03201 | 1 | 1 | 3 | 2 | 548 | 9.0968 |
25 | 02501 | 1 | 1 | 3 | 2 | 505 | 9.2633 |
25 | 02501 | 1 | 2 | 3 | 2 | 447 | 9.0084 |
01 | 00101 | 1 | 1 | 3 | 3 | 412 | 9.1381 |
01 | 00101 | 1 | 1 | 2 | 1 | 401 | 8.8231 |
32 | 03203 | 1 | 2 | 3 | 2 | 393 | 8.9166 |
32 | 03201 | 1 | 1 | 3 | 3 | 390 | 9.0601 |
El paso a seguir es unificar las tablas creadas.
<- inner_join(encuesta_df_agg, statelevel_predictors_df) encuesta_df_agg
11.2.4 Definiendo el modelo multinivel.
Después de haber ordenado la encuesta, podemos pasar a la definición del modelo.
options(MC.cores=parallel::detectCores()) # Permite procesar en paralelo.
<- stan_lmer(
fit ~ # Ingreso medio (Y)
logingreso 1 | dam2) + # Efecto aleatorio (ud)
(+ # Efecto fijo (Variables X)
edad +
sexo +
tasa_desocupacion +
luces_nocturnas +
cubrimiento_cultivo
cubrimiento_urbano ,weights = n, # Número de observaciones.
data = encuesta_df_agg, # Encuesta agregada
verbose = TRUE, # Muestre el avance del proceso
chains = 4, # Número de cadenas.
iter = 1000 # Número de realizaciones de la cadena
)saveRDS(fit, file = "Recursos/Día4/Sesion1/Data/fit_ingresos.rds")
Después de esperar un tiempo prudente se obtiene el siguiente modelo.
<- readRDS("Recursos/Día4/Sesion1/Data/fit_ingresos.rds")
fit tba(coef(fit)$dam2 %>% head(10))
(Intercept) | edad2 | edad3 | edad4 | edad5 | sexo2 | tasa_desocupacion | luces_nocturnas | cubrimiento_cultivo | cubrimiento_urbano | |
---|---|---|---|---|---|---|---|---|---|---|
00101 | 8.8056 | 0.2619 | 0.3041 | 0.5292 | 0.5353 | -0.0924 | 25.7452 | 0.1079 | 0.0256 | -0.0858 |
00201 | 8.8603 | 0.2619 | 0.3041 | 0.5292 | 0.5353 | -0.0924 | 25.7452 | 0.1079 | 0.0256 | -0.0858 |
00202 | 8.6616 | 0.2619 | 0.3041 | 0.5292 | 0.5353 | -0.0924 | 25.7452 | 0.1079 | 0.0256 | -0.0858 |
00203 | 8.6011 | 0.2619 | 0.3041 | 0.5292 | 0.5353 | -0.0924 | 25.7452 | 0.1079 | 0.0256 | -0.0858 |
00204 | 9.1334 | 0.2619 | 0.3041 | 0.5292 | 0.5353 | -0.0924 | 25.7452 | 0.1079 | 0.0256 | -0.0858 |
00205 | 8.6218 | 0.2619 | 0.3041 | 0.5292 | 0.5353 | -0.0924 | 25.7452 | 0.1079 | 0.0256 | -0.0858 |
00206 | 8.6877 | 0.2619 | 0.3041 | 0.5292 | 0.5353 | -0.0924 | 25.7452 | 0.1079 | 0.0256 | -0.0858 |
00208 | 8.7539 | 0.2619 | 0.3041 | 0.5292 | 0.5353 | -0.0924 | 25.7452 | 0.1079 | 0.0256 | -0.0858 |
00210 | 9.0558 | 0.2619 | 0.3041 | 0.5292 | 0.5353 | -0.0924 | 25.7452 | 0.1079 | 0.0256 | -0.0858 |
00301 | 8.5342 | 0.2619 | 0.3041 | 0.5292 | 0.5353 | -0.0924 | 25.7452 | 0.1079 | 0.0256 | -0.0858 |
Validación del modelo
library(posterior)
library(bayesplot)
mcmc_dens_chains(fit,pars = "sigma") +
(mcmc_areas(fit,pars = "sigma"))/
mcmc_trace(fit,pars = "sigma")
<- c("edad2", "edad3", "edad4", "edad5", "sexo2",
var_names "luces_nocturnas", "cubrimiento_urbano","cubrimiento_cultivo")
mcmc_areas(fit,pars = var_names)
mcmc_trace(fit,pars = var_names)
<- inner_join(encuesta_mrp, statelevel_predictors_df)
encuesta_mrp2 <- posterior_epred(fit, newdata = encuesta_mrp2)
y_pred_B <- sample(nrow(y_pred_B), 100)
rowsrandom <- y_pred_B[rowsrandom, ]
y_pred2
ppc_dens_overlay(y = as.numeric(encuesta_mrp2$logingreso),
/
y_pred2)ppc_dens_overlay(y = exp(as.numeric(encuesta_mrp2$logingreso))-1,
exp(y_pred2)-1)) (