T4: ENOE t223

Introducción

Aquí dejo la presentación

Descarga el proyecto desde acá

En esta liga puedes descarga el proyecto de trabajo. De esta manera no tendremos problemas con las rutas relativas.

https://tinyurl.com/demos-talleres

Paquetes

if (!require("pacman")) install.packages("pacman") # instala pacman si se requiere
Loading required package: pacman
pacman::p_load(tidyverse,
               haven,
               sjlabelled,
               pollster,
               janitor) #carga los paquetes necesarios 

Un mini repaso

a <- 2

b <- c("a", "b")

c <- c(NA, T, F,2)

NA==F
[1] NA
sum(NA, T, F, 2)
[1] NA
sum(c)
[1] NA
sum(c, na.rm=T)
[1] 3

Datos primera parte

Vamos a fusionar la ENOE, se ha descargado desde INEGI su versión .dta

vivt223 <- haven::read_dta("data_t4/2023trim2_dta/VIVT223.dta") 
hogt223 <- haven::read_dta("data_t4/2023trim2_dta/HOGT223.dta")
sdemt223 <- haven::read_dta("data_t4/2023trim2_dta/SDEMT223.dta")
coe1t223 <- haven::read_dta("data_t4/2023trim2_dta/COE1T223.dta")
coe2t223 <- haven::read_dta("data_t4/2023trim2_dta/COE2T223.dta")

Fusionado uno a uno de los COE

Estas dos tablas sólo son para mayores de 12 años

coet223 <- coe1t223 %>% 
  dplyr::inner_join(coe2t223)
Joining with `by = join_by(cd_a, ent, con, upm, d_sem, n_pro_viv, v_sel, n_hog,
h_mud, n_ent, per, n_ren, eda, n_inf, ur, tipo, mes_cal, fac_tri, fac_men)`

Hay tres opciones más de join

help("mutate-joins")

Fusionado de las otras tablas

idviv <- c("tipo", "mes_cal", "cd_a", "ent", "con", "v_sel")
idhog <- c(idviv, "n_hog", "h_mud")
idsdem <- c(idhog, "n_ren" )

No queremos viviendas vacías

enoe0<-vivt223 %>% 
  dplyr::inner_join(hogt223, by=idviv)

dim(enoe0)
[1] 151329     56

Revisemos esta base

names(enoe0)
 [1] "loc.x"       "mun.x"       "est.x"       "est_d_tri.x" "est_d_men.x"
 [6] "ageb.x"      "t_loc_tri.x" "t_loc_men.x" "cd_a"        "ent"        
[11] "con"         "upm.x"       "d_sem.x"     "n_pro_viv.x" "v_sel"      
[16] "n_ent.x"     "per.x"       "p1"          "p2"          "p3"         
[21] "ur.x"        "tipo"        "mes_cal"     "fac_tri.x"   "fac_men.x"  
[26] "loc.y"       "mun.y"       "est.y"       "est_d_tri.y" "est_d_men.y"
[31] "ageb.y"      "t_loc_tri.y" "t_loc_men.y" "upm.y"       "d_sem.y"    
[36] "n_pro_viv.y" "n_hog"       "h_mud"       "n_ent.y"     "per.y"      
[41] "r_pre"       "p_dia"       "p_mes"       "p_anio"      "r_def"      
[46] "d_dia"       "d_mes"       "d_anio"      "e_obs"       "p4_1"       
[51] "p4_2"        "inf"         "ur.y"        "tipolev"     "fac_tri.y"  
[56] "fac_men.y"  
enoe0 %>% 
  count(fac_tri.x==fac_tri.y)
# A tibble: 2 × 2
  `fac_tri.x == fac_tri.y`      n
  <lgl>                     <int>
1 FALSE                       135
2 TRUE                     151194

¿Por qué pasa esto?

No hay hogares en esas viviendas, hay valores en la base x, pero no en la base y

enoe0 %>% 
  dplyr::filter(!fac_tri.x==fac_tri.y) %>% 
  janitor::tabyl(fac_tri.x, fac_tri.y)
 fac_tri.x 0
        12 1
        20 2
        21 1
        22 2
        24 1
        28 1
        32 1
        33 1
        34 1
        36 1
        39 3
        43 1
        44 1
        47 1
        48 1
        49 1
        52 3
        64 1
        65 1
        66 2
        68 2
        69 2
        70 2
        71 1
        74 1
        76 1
        78 1
        79 1
        83 1
        85 2
        88 2
        90 1
        93 2
        98 1
       100 1
       101 2
       103 1
       107 1
       111 1
       118 1
       123 1
       126 2
       130 1
       134 4
       136 2
       142 2
       143 1
       147 2
       149 1
       151 1
       152 1
       161 1
       162 1
       163 1
       166 2
       167 1
       168 1
       172 1
       189 1
       191 1
       194 1
       198 1
       199 3
       201 1
       202 1
       203 1
       217 2
       221 1
       227 1
       232 1
       243 2
       255 1
       261 1
       264 1
       267 2
       282 2
       301 2
       328 1
       344 1
       361 1
       381 1
       398 1
       404 1
       416 1
       428 1
       485 1
       492 4
       495 3
       529 2
       549 1
       643 1
       709 1
       785 1
       827 1
       872 1
      1136 1
      1237 1
      1302 2
      4275 1

Obviamente, vamos quedarnos con la información.

enoe0<-enoe0 %>% 
  dplyr::select(-ends_with(".y")) %>% # quita las variables que terminan con .y
  dplyr::rename_at(vars(ends_with(".x")), ~ stringr::str_remove(.x, ".x")) # renombra todas las variables que terminan en .x quitándoles el sufijo

Hoy pegaremos de manera similar a los individuos, pero primero nos vamos a quedar con quiénes tienen resultados definitivos de entrevistas completas

enoe0 %>% 
  count(as_label(r_def))
# A tibble: 14 × 2
   `as_label(r_def)`                                             n
   <fct>                                                     <int>
 1 Entrevista completa                                      125951
 2 Nadie en el momento de la entrevista                       4876
 3 Ausente temporal                                           1659
 4 Se negó a dar información                                  5441
 5 Informante inadecuado                                       201
 6 Otro motivo                                                2496
 7 Adecuada para habitarse                                    5751
 8 De uso temporal                                            3489
 9 Inadecuada para habitarse                                   322
10 De uso temporal para fines diferentes de habitación         481
11 Demolida                                                     80
12 Uso permanente para fines diferentes a los de habitación    262
13 El hogar se mudó                                             79
14 Entrevista suspendida                                       241
sdemt223 %>% 
  count(as_label(c_res))
# A tibble: 3 × 2
  `as_label(c_res)`       n
  <fct>               <int>
1 Residente habitual 418269
2 Ausente definitivo   7406
3 Nuevo residente      5474
enoe0 <- enoe0 %>% 
  filter(r_def==0) #entrevista completa

sdemt223 <- sdemt223 %>% 
  filter(r_def==0) %>% 
  filter(!c_res==2) # residente que no es ausente
enoe1<-enoe0 %>% 
  dplyr::left_join(sdemt223, by=idhog) %>% 
  dplyr::select(-ends_with(".y")) %>% # quita las variables que terminan con .y
  dplyr::rename_at(vars(ends_with(".x")), ~ stringr::str_remove(.x, ".x")) 
Warning: `cd_a` and `cd_a` have conflicting value labels.
ℹ Labels for these values will be taken from `cd_a`.
✖ Values: 1
dim(enoe1)
[1] 422778    129

Ya tenemos lista una base de individuos que podemos pegar con nuestra base de coe. Pero revisemos que este cuestionario tiene preguntas simulares a la cuestionario de otras tablas

intersect(names(enoe1), names(coet223))
 [1] "cd_a"      "ent"       "con"       "upm"       "d_sem"     "n_pro_viv"
 [7] "v_sel"     "n_ent"     "per"       "p1"        "p3"        "ur"       
[13] "tipo"      "mes_cal"   "fac_tri"   "fac_men"   "n_hog"     "h_mud"    
[19] "r_def"     "p4_1"      "p4_2"      "n_ren"     "eda"      
coet223<- coet223 %>% 
  dplyr::rename_at(vars(p1, p3, p4_1, p4_2), ~ paste0(.x, "coe") )%>% 
  dplyr::select(-ends_with(".y")) %>% # quita las variables que terminan con .y
  dplyr::rename_at(vars(ends_with(".x")), ~ stringr::str_remove(.x, ".x")) 

names(coet223)
  [1] "r_def"     "cd_a"      "ent"       "con"       "upm"       "d_sem"    
  [7] "n_pro_viv" "v_sel"     "n_hog"     "h_mud"     "n_ent"     "per"      
 [13] "n_ren"     "eda"       "n_inf"     "p1coe"     "p1a1"      "p1a2"     
 [19] "p1a3"      "p1b"       "p1c"       "p1d"       "p1e"       "p2_1"     
 [25] "p2_2"      "p2_3"      "p2_4"      "p2_9"      "p2a_dia"   "p2a_sem"  
 [31] "p2a_mes"   "p2a_anio"  "p2b_dia"   "p2b_sem"   "p2b_mes"   "p2b_anio" 
 [37] "p2b"       "p2c"       "p2d1"      "p2d2"      "p2d3"      "p2d4"     
 [43] "p2d5"      "p2d6"      "p2d7"      "p2d8"      "p2d9"      "p2d10"    
 [49] "p2d11"     "p2d99"     "p2e"       "p2f"       "p2g1"      "p2g2"     
 [55] "p2h1"      "p2h2"      "p2h3"      "p2h4"      "p2h9"      "p2i"      
 [61] "p2j"       "p2k_anio"  "p2k_mes"   "p2k"       "p3coe"     "p3a"      
 [67] "p3b"       "p3c1"      "p3c2"      "p3c3"      "p3c4"      "p3c9"     
 [73] "p3d"       "p3e"       "p3f1"      "p3f2"      "p3g1_1"    "p3g1_2"   
 [79] "p3g2_1"    "p3g2_2"    "p3g3_1"    "p3g3_2"    "p3g4_1"    "p3g4_2"   
 [85] "p3g9"      "p3g_tot"   "p3h"       "p3i"       "p3j1"      "p3j2"     
 [91] "p3k1"      "p3k2"      "p3k3"      "p3k4"      "p3k5"      "p3k9"     
 [97] "p3l"       "p4"        "p4_1coe"   "p4_2coe"   "p4_3"      "p4a"      
[103] "p4a_1"     "p4b"       "p4c"       "p4d1"      "p4d2"      "p4d3"     
[109] "p4e"       "p4f"       "p4g"       "p4h"       "p4i"       "p4i_1"    
[115] "p5"        "p5a"       "p5b_hlu"   "p5b_mlu"   "p5b_hma"   "p5b_mma"  
[121] "p5b_hmi"   "p5b_mmi"   "p5b_hju"   "p5b_mju"   "p5b_hvi"   "p5b_mvi"  
[127] "p5b_hsa"   "p5b_msa"   "p5b_hdo"   "p5b_mdo"   "p5b_thrs"  "p5b_tdia" 
[133] "p5c"       "p5d1"      "p5d_hlu"   "p5d_mlu"   "p5d_hma"   "p5d_mma"  
[139] "p5d_hmi"   "p5d_mmi"   "p5d_hju"   "p5d_mju"   "p5d_hvi"   "p5d_mvi"  
[145] "p5d_hsa"   "p5d_msa"   "p5d_hdo"   "p5d_mdo"   "p5d_thrs"  "p5d_tdia" 
[151] "p5e"       "p5f1"      "p5f2"      "p5f3"      "p5f4"      "p5f5"     
[157] "p5f6"      "p5f7"      "p5f8"      "p5f9"      "p5f10"     "p5f11"    
[163] "p5f12"     "p5f13"     "p5f14"     "p5f15"     "p5f99"     "ur"       
[169] "tipo"      "mes_cal"   "fac_tri"   "fac_men"   "p6_1"      "p6_2"     
[175] "p6_3"      "p6_4"      "p6_5"      "p6_6"      "p6_7"      "p6_8"     
[181] "p6_9"      "p6_10"     "p6_99"     "p6a1"      "p6a2"      "p6a3"     
[187] "p6a4"      "p6a9"      "p6b1"      "p6b2"      "p6c"       "p6d"      
[193] "p6e"       "p6e_c"     "p6f"       "p6f_c"     "p6g"       "p6h"      
[199] "p6h_c"     "p6i"       "p6i_c"     "p7"        "p7a"       "p7b"      
[205] "p7c"       "p8_1"      "p8_2"      "p8_3"      "p8_4"      "p8_9"     
[211] "p8a"       "p9_1"      "p9_h1"     "p9_m1"     "p9_2"      "p9_h2"    
[217] "p9_m2"     "p9_3"      "p9_h3"     "p9_m3"     "p9_4"      "p9_h4"    
[223] "p9_m4"     "p9_5"      "p9_h5"     "p9_m5"     "p9_6"      "p9_h6"    
[229] "p9_m6"     "p9_7"      "p9_h7"     "p9_m7"     "p9_8"      "p9_h8"    
[235] "p9_m8"    

Base final:

enoet223 <- enoe1 %>% 
  left_join(coet223)
Joining with `by = join_by(cd_a, ent, con, upm, d_sem, n_pro_viv, v_sel, n_ent,
per, ur, tipo, mes_cal, fac_tri, fac_men, n_hog, h_mud, r_def, n_ren, eda)`
dim(enoet223)
[1] 422778    345

Vamos a quitar algunos objetos para mejorar nuestro uso de memoria

rm(vivt223, hogt223, coe1t223, coe2t223, coet223, enoe0, enoe1)
gc()
            used   (Mb) gc trigger   (Mb) limit (Mb)  max used   (Mb)
Ncells   1152198   61.6    1997454  106.7         NA   1997454  106.7
Vcells 196127078 1496.4  540486262 4123.6      16384 450328647 3435.8

Algunos tabulados de la ENOE

## Sin expansión
enoet223 %>%
  filter(eda>14 & eda<99) %>% 
  mutate(clase1=as_label(clase1)) %>% 
  janitor::tabyl(clase1)
                             clase1      n percent
                          No aplica      0 0.00000
    Población económicamente activa 201003 0.60978
 Población no económicamente activa 128629 0.39022
## Con expansión
enoet223 %>%
  filter(eda>14 & eda<99) %>% # este el filtro que usa inegi para sus tabulados
  mutate(clase1=as_label(clase1)) %>% 
  pollster::topline(clase1, weight = fac_tri)
# A tibble: 2 × 5
  Response                Frequency Percent `Valid Percent` `Cumulative Percent`
  <fct>                       <dbl>   <dbl>           <dbl>                <dbl>
1 Población económicamen…  60216432    60.2            60.2                 60.2
2 Población no económica…  39834351    39.8            39.8                100  

Siempre checa que tus tabulados sean como los de INEGI de tu variable a estudiar

De doble entrada

## Sin expansión
enoet223 %>%
  filter(eda>14 & eda<99) %>% 
  mutate(clase1=as_label(clase1)) %>% 
  mutate(clase2=as_label(clase2)) %>% 
  janitor::tabyl(clase1, clase2)
                             clase1 No aplica Población ocupada
                          No aplica         0                 0
    Población económicamente activa         0            195374
 Población no económicamente activa         0                 0
 Población desocupada Disponibles No disponibles
                    0           0              0
                 5629           0              0
                    0       16467         112162
## Con expansión
enoet223 %>%
  filter(eda>14 & eda<99) %>% # este el filtro que usa inegi para sus tabulados
  mutate(clase1=as_label(clase1)) %>% 
  mutate(clase2=as_label(clase2)) %>% 
  pollster::crosstab(clase1, clase2, weight = fac_tri)
# A tibble: 2 × 6
  clase1 `Población ocupada` `Población desocupada` Disponibles `No disponibles`
  <fct>                <dbl>                  <dbl>       <dbl>            <dbl>
1 Pobla…                97.2                   2.81         0                0  
2 Pobla…                 0                     0           13.0             87.0
# ℹ 1 more variable: n <dbl>

Ingresos

Para los ingresos, INEGI publica los válidos, es decir los mayores a cero.

enoet223 %>% 
  filter(eda>14 & eda<99) %>% 
  filter(ing_x_hrs>0) %>% # ojo
  summarise(promedio=weighted.mean(ing_x_hrs, w = fac_tri))
# A tibble: 1 × 1
  promedio
     <dbl>
1     54.4

Segunda parte: panel rotativo

El panel rotativo. Para hacer un ejemplo vamos a pegar únicamente el cuestionario sociodemográfico. Y sólo podemos pegar las entrevistas cara a cara

Datos segunta parte

Vamos a trabajar con el panel que inicia el t222 y termina en t2 de 2023. Para que no sea tan pesado el ambiente aprovechamos y hacermos más filtros incluyendo el número de entrevista correspondiente.

sdemt222 <- read_dta("data_t4/anterior/SDEMT222.dta") %>% 
  filter(tipo==1) %>% # sólo cara cara
  filter(r_def==0) %>% # sólo completa
  filter(!c_res==2) %>%  #no ausentes definitivos
  filter(n_ent==1) %>% 
  mutate(trim="t222") %>% 
  mutate_at(vars(cs_p20a_1, cs_p20a_c, 
                 cs_p20b_1, cs_p20b_c,
                 cs_p20c_1), ~ as.numeric(.x))

sdemt322 <- read_dta("data_t4/anterior/SDEMT322.dta") %>% 
  filter(tipo==1) %>% # sólo cara cara
  filter(r_def==0) %>% # sólo completa
  filter(!c_res==2) %>%  #no ausentes definitivos
  filter(n_ent==2) %>% 
  mutate(trim="t322") 


sdemt422 <- read_dta("data_t4/anterior/SDEMT422.dta") %>% 
  filter(tipo==1) %>% # sólo cara cara
  filter(r_def==0) %>% # sólo completa
  filter(!c_res==2) %>% #no ausentes definitivos
  filter(n_ent==3)  %>% 
  mutate(trim="t422") 


sdemt123 <- read_dta("data_t4/anterior/SDEMT123.dta")%>% 
  filter(tipo==1) %>% # sólo cara cara
  filter(r_def==0) %>% # sólo completa
  filter(!c_res==2) %>%  #no ausentes definitivos
  filter(n_ent==4) %>% 
  mutate(trim="t123") 

sdemt223<-sdemt223 %>% 
  filter(tipo==1) %>% 
  filter(n_ent==5) %>% 
  mutate(trim="t223") 

Vamos a hacer el panel hoy

panel<- dplyr::bind_rows(sdemt222, # había un conflicto en cs_p20*
                         sdemt322, 
                         sdemt422, 
                         sdemt123,
                         sdemt223)
Warning: `..1$tcco` and `..2$tcco` have conflicting value labels.
ℹ Labels for these values will be taken from `..1$tcco`.
✖ Values: 2
Warning: `..1$tcco` and `..3$tcco` have conflicting value labels.
ℹ Labels for these values will be taken from `..1$tcco`.
✖ Values: 2
Warning: `..1$cd_a` and `..4$cd_a` have conflicting value labels.
ℹ Labels for these values will be taken from `..1$cd_a`.
✖ Values: 81, 82, 83, 84, 85, and 86
Warning: `..1$tcco` and `..4$tcco` have conflicting value labels.
ℹ Labels for these values will be taken from `..1$tcco`.
✖ Values: 2
Warning: `..1$tcco` and `..5$tcco` have conflicting value labels.
ℹ Labels for these values will be taken from `..1$tcco`.
✖ Values: 2

Los warnigns son solo de las etiquetas que son diferentes

panel %>% 
  mutate(n_ent=as_label(n_ent)) %>% 
  tabyl(n_ent)
              n_ent     n   percent
 Primera entrevista 80588 0.2039748
 Segunda entrevista 79861 0.2021347
 Tercera entrevista 79046 0.2000719
  Cuarta entrevista 77951 0.1973003
  Quinta entrevista 77642 0.1965182

Vamos a revisar los id

panel %>% 
  janitor::get_dupes(cd_a, ent, con, v_sel, n_hog, h_mud, n_ren, n_ent)
No duplicate combinations found of: cd_a, ent, con, v_sel, n_hog, h_mud, n_ren, n_ent
# A tibble: 0 × 116
# ℹ 116 variables: cd_a <dbl+lbl>, ent <dbl+lbl>, con <dbl>, v_sel <dbl+lbl>,
#   n_hog <dbl+lbl>, h_mud <dbl+lbl>, n_ren <dbl+lbl>, n_ent <dbl+lbl>,
#   dupe_count <int>, r_def <dbl+lbl>, loc <dbl>, mun <dbl>, est <dbl>,
#   est_d_tri <dbl>, est_d_men <dbl>, ageb <dbl>, t_loc_tri <dbl+lbl>,
#   t_loc_men <dbl+lbl>, upm <dbl>, d_sem <dbl+lbl>, n_pro_viv <dbl>,
#   per <dbl+lbl>, c_res <dbl+lbl>, par_c <dbl>, sex <dbl+lbl>, eda <dbl>,
#   nac_dia <dbl+lbl>, nac_mes <dbl+lbl>, nac_anio <dbl>, l_nac_c <dbl+lbl>, …
panel %>% 
  janitor::get_dupes(cd_a, ent, con, v_sel, n_hog, h_mud, n_ren) %>% 
  tabyl(dupe_count)
 dupe_count      n    percent
          2  15820 0.04118279
          3  21696 0.05647926
          4  37980 0.09886995
          5 308645 0.80346800

Vamos a verificar con la edad si se trata de los mismos individuos

panel<-panel %>% 
  mutate(edad_min=min(eda), 
            edad_max=max(eda),
            .by = c(cd_a, ent, con, v_sel, n_hog, h_mud, n_ren)) %>% 
  mutate(diff_eda=edad_max-edad_min)

panel %>% 
  tabyl(diff_eda)
 diff_eda      n    percent
        0  39524 0.10003847
        1 349991 0.88585581
        2   5573 0.01410572

Vamos a hacer una variable que nos diga cuántas entrevista tiene cada individuo:

panel<-panel %>% 
  mutate(total_n=sum(tipo),
         .by = c(cd_a, ent, con, v_sel, n_hog, h_mud, n_ren)) 

panel<-panel %>% 
  filter(total_n==5)

De long a wide

No vamos a trabajar con toda la base, sino con la variable clase 2

panel_corto<-panel %>% 
  select(cd_a, ent, con, v_sel, n_hog, h_mud, n_ren, n_ent, clase2) %>% 
  tidyr::pivot_wider(values_from = clase2,
                     names_from = n_ent, 
                     names_prefix = "clase2_")
panel_corto %>% 
  filter(clase2_1>0) %>% 
  mutate_at(vars(starts_with("clase2")), ~ as_label(.x)) %>% 
  tabyl(clase2_1, clase2_2, show_missing_levels = F)
             clase2_1 Población ocupada Población desocupada Disponibles
    Población ocupada             24497                  429         609
 Población desocupada               455                  155          70
          Disponibles               880                  103         528
       No disponibles              2167                  183        1655
 No disponibles
           2699
            206
           1903
          14471

Para incluir más variables, debemos de considerar cuáles cambian en el tiempo:

panel_corto<-panel %>% 
  select(cd_a, ent, con, v_sel, n_hog, h_mud, n_ren, n_ent, eda, clase2) %>% 
  mutate(clase2=as_label(clase2)) %>% 
  tidyr::pivot_wider(values_from = c(clase2, eda),
                     names_from = n_ent, 
                     names_glue = "{.value}_{n_ent}") # esto hace que la variables de -value vayan primero
names(panel_corto)
 [1] "cd_a"     "ent"      "con"      "v_sel"    "n_hog"    "h_mud"   
 [7] "n_ren"    "clase2_1" "clase2_2" "clase2_3" "clase2_4" "clase2_5"
[13] "eda_1"    "eda_2"    "eda_3"    "eda_4"    "eda_5"   

Algunas cosas para pensar

  • ¿Qué pasa con los factores de expansión?

  • ¿Cómo calcularías cuál es porcentaje de atrición?

  • ¿Qué pasa con el COE que cambia en t1?