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.

 
comments powered by Disqus