Muestreando II

Ya estuve hablando algo del partial pooling y existe un caso en el que es particularmente útil, se trata de cuando tenemos que estimar en áreas pequeñas. Entendamos áreas pequeñas cuando tenemos pocos datos en alguna o algunas categorías de una variable categórica.

Continuando con el ejemplo de la anterior entrada, veamos qué sucede con las estimaciones de la tasa de paro en cada provincia y cómo nos pueden ayudar los modelos mixtos.

Leemos los datos

library(MicroDatosEs)
library(tidyverse)
library(lme4)

fpath <- "~/Dropbox/Public/datos_4t18/md_EPA_2018T4.txt"

epa <- epa2005(fpath)
names(epa) <- tolower(names(epa))
epa <- epa[, c("prov", "edad", "nforma", "aoi")]

Recodificamos

recodificacion <- function(dat) {
  
  dat$aoi[grepl("^Inactivos", dat$aoi)] <- "i"
  dat$aoi[grepl("[O-o]cupados", dat$aoi)] <- "o"
  dat$aoi[grepl("^Parados", dat$aoi)] <- "p"
  
  dat$aoi <- factor(dat$aoi)
  
  dat$gedad <- dat$edad
  
  dat$gedad[dat$edad == "de 0 A 4 años" |
              dat$edad == "de 5 A 9 años" |
              dat$edad == "de 10 A 15 años"] <- "15 años o menos "
  
  dat$gedad[dat$edad == "de 16 A 19 años" |
              dat$edad == "de 20 A 24 años" |
              dat$edad == "de 25 A 29 años" |
              dat$edad == "de 30 A 34 años"] <- "De 16 a 34"
  
  dat$gedad[dat$edad == "de 35 A 39 años" |
              dat$edad == "de 40 A 44 años" |
              dat$edad == "de 45 A 49 años" |
              dat$edad == "de 50 A 54 años"] <- "De 35 a 54"
  
  dat$gedad[dat$edad == "de 55 A 59 años" |
              dat$edad == "de 60 A 64 años" |
              dat$edad == "65 o más años"] <- "55 o más"
  
  dat$gedad <-
    factor(dat$gedad,
           levels = c("15 años o menos ", "De 16 a 34", "De 35 a 54", "55 o más"))
  
  dat
}

epa <- recodificacion(epa)

Quitamos menores de 15 años e inactivos

# eliminar menores de 16 años  
epa <- epa[epa$gedad != "15 años o menos ", ]

# eliminar inactivos
epa <- epa[epa$aoi != "i", ]

epa <- epa[, c("aoi","gedad","prov")]

# quitamos niveles sobrantes y convetimos provincia en tipo factor

epa$gedad <- droplevels(epa$gedad)
epa$prov <- factor(epa$prov)

# calculamos número de filas en cada provincia
epa <- epa %>%
  group_by(prov) %>% 
  mutate(tam = n()) %>% 
  ungroup

epa$prov <- reorder(epa$prov, epa$tam)  

head(epa)
## # A tibble: 6 x 4
##   aoi   gedad      prov    tam
##   <fct> <fct>      <fct> <int>
## 1 o     De 35 a 54 Álava   722
## 2 o     De 35 a 54 Álava   722
## 3 o     De 35 a 54 Álava   722
## 4 o     De 35 a 54 Álava   722
## 5 o     De 35 a 54 Álava   722
## 6 o     De 35 a 54 Álava   722

Estimaciones usando muestreo y modelos mixtos

Dividimos los datos en 2. Una parte para tener una estimación de “referencia” y otra para muestrear y ver si se parece o no a la estimación de referencia.

epa$id <- seq_len(nrow(epa))

# Muestreo estratificando por provincia y grupo de edad

muestra_base <- epa %>% 
  group_by(prov, gedad) %>% 
  sample_frac(0.5) %>% 
  ungroup

epa_remain <- epa %>% anti_join(muestra_base, by = "id") 

La estimación que tomaremos como referencia será

estim_tparo <- muestra_base %>%
  group_by(prov, gedad) %>%
  summarise(tparo = mean(aoi == "p", na.rm = TRUE),
            tam = first(tam)) %>% 
  ungroup

DT::datatable(estim_tparo)

Construimos data.frame con todas las combinaciones de provincia y grupo de edad que será nuestro data.frame a predecir por el modelo mixto

dat_ficti <- expand.grid(prov = levels(epa$prov), gedad = levels(epa$gedad))

head(dat_ficti)
##       prov      gedad
## 1   Ceuta  De 16 a 34
## 2  Melilla De 16 a 34
## 3    Soria De 16 a 34
## 4   Huelva De 16 a 34
## 5 Palencia De 16 a 34
## 6   Zamora De 16 a 34

Creamos función para estimar según un modelo mixto y calculamos el error con respecto a las estimaciones base y también comparamos con las estimaciones directas y con un modelo logit clásico que tenga los efectos principales de provincia y edad.

Nótese que las estimaciones directas coinciden con las estimaciones usando un modelo logit clásico que tenga los efectos principales y la interacción entre provincia y edad.

Estimar_tparo <- function(muestra, dat_ficti,...) {
  
  modelo_glmer <- glmer(aoi == "p" ~ (1 |prov) + (1 | gedad),
                        data = muestra,
                        family = binomial)
  
  modelo_clasico <- glm(aoi == "p" ~  prov + gedad,
                        data = muestra,
                        family = binomial )
  
  
  # con modelos mixtos se pueden estimar hasta categorías qeu no estén en la muestra
  
  dat_ficti$tparo_glmer <- predict(modelo_glmer,
                                  newdata = dat_ficti,
                                  type = "response",
                                  allow.new.levels = TRUE)
  
  predict_glm_safely <- possibly(
    function(modelo, newdata){
      predict(modelo, newdata = newdata,
      type = "response")},
    otherwise = NA)
  
  dat_ficti$tparo_glm <- predict_glm_safely(modelo_clasico, dat_ficti)
  
  estim_directas <-  muestra %>%
    group_by(prov, gedad) %>%
    summarise(tparo_directa = mean(aoi == "p", na.rm = TRUE))
  
  res <- dat_ficti %>%
    left_join(estim_tparo, by = c("prov", "gedad")) %>%
    left_join(estim_directas, by = c("prov", "gedad")) %>% 
    mutate(
      error_abs_glmer =  abs(tparo - tparo_glmer),
      error_abs_glm = abs(tparo - tparo_glm),
      error_abs_directas = abs(tparo - tparo_directa))
  res
}

Creamos función para pintar los errores con respecto a la estimación de referencia. Cada punto es la estimación en una provincia e intervalo de edad por cada uno de los métodos.

plot_errores <- function(res, title, span = 1){
  res_tidyr <- res %>%
    select(prov, gedad, tam, error_abs_glmer, error_abs_glm, error_abs_directas) %>%
    gather(tipo, error_abs, -prov , -gedad, -tam)

  
  res_tidyr %>%
    ggplot(aes(x = tam, y = error_abs, col = tipo)) +
    geom_point(size = rel(0.6)) +
    geom_smooth(span = span, se = FALSE) +
    facet_wrap(~gedad) +
    ylim(0,0.5) +
    labs(x = "Individuos en cada provincia", title = title) 

}

Muestra del 5% que se corresponden con 1864 datos

res_1 <-  Estimar_tparo(muestra = epa_remain %>% sample_frac(0.05), dat_ficti = dat_ficti)

plot_errores(res_1, "Muestra del 5%")
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
## Warning: Removed 2 rows containing non-finite values (stat_smooth).
## Warning: Removed 2 rows containing missing values (geom_point).

Muestras de 10% que se corresponden con 3727 datos

res_10 <-  Estimar_tparo(muestra = epa_remain %>% sample_frac(0.1), dat_ficti = dat_ficti)

plot_errores(res_10, "Muestra del 10%")
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

Muestras de 50% que se corresponden con 1.863610^{4} datos

res_50 <-  Estimar_tparo(muestra = epa_remain %>% sample_frac(0.5), dat_ficti = dat_ficti)

plot_errores(res_50, "Muestra del 50%")
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

Y vemos que con poco tamaño muestral, el modelo con glmer es mucho mejor y conforme aumenta el tamaño muestral se van igualando. Cómo decía un lector del blog “de dónde no hay no se puede sacar”, pero hagamos lo posible por sacar algo.