22 min read

Exploración de la base de datos ENES-PISAC

Introducción

Desde hace un tiempo está disponible y con acceso público la base de datos de la Encuesta Nacional sobre la Estructura Social de Argentina, generado en el marco del Programa de Investigación sobre la Argentina Contemporánea, PISAC.

Los antecedentes de esta encuesta se reúnen en el volúmen Estudios sobre la estructura social en la Argentina Contemporánea, de acceso libre.

El libro Cómo somos, vivimos y convivimos en una sociedad desigual presenta una descripción general de la base de datos, así como diversos capítulos elaborados por especialistas en los que se presentan algunos de los principales hallazgos de la investigación organizados en tres secciones: Estructura social, Condiciones de vida y materialización de derechos y Composición, prácticas y estrategias de los hogares.

La base de datos y documentos técnicos (cuestionario, libro de códigos, etc) están disponibles en portal del PISAC. Lamentablemente para descargar los archivos con los datos es necesario completar un formulario con datos personales y laborales, incluido un correo electrónico. De todas maneras no hay verificación de la dirección de correo.

Los datos son sumamente valiosos para responder muchas preguntas sobre la estructura de la sociedad argentina en materia de desigualdades de diverso tipo (económicas, espaciales, de género, educativas). Sin embargo una cosa es acceder a los datos en bruto y otra poder analizarlos y buscar respuestas a esas preguntas. Este post procura contribuir en ese sentido, presentando un punto de partida para analizar las bases de datos de la ENES con R. R es un software libre de análisis de datos, de descarga gratuita y código abierto. El problema de R es su curva de aprendizaje, más bien empinada en el primer tramo. Para facilitar la aplicación de esta herramienta de análisis a estos datos presento una serie de procesos –documentados y con código- que pueden servir como punto de partida:

  1. Importación de la base de datos a partir de archivos de SPSS
  2. Generación de un diccionario de variables utilizable en R a partir de los metadatos del archivo
  3. Unión de los datos de personas y hogares, permitiendo el uso simultaneo de todas las variables
  4. Utilización del ponderador muestral incluido en la base de datos para la estimación de proporciones
  5. Uso del método bootstrap para dar cuenta de la incertidumbre en la estimación de proporciones

Dicho de otro modo, me enfoco exclusivamente en aspectos técnicos de la base de datos y, sobre todo, el manejo de la misma con R. Es decir un primer para comenzar a analizar estos datos de manera apropiada.

Librerías

Para el manejo de la base de datos utilizaremos las librerías del tidyverse, entre otras cosas porque disponen de una interfaz razonablemente consistente para el uso de ponderadores muestrales.

library(haven)
library(tidyverse)

Carga

Como la base de datos no está expuesta en una ubicación http es requisito previo descargarla y copiarla a una ubicación local de nuestra computadora, preferentemente en una carpeta dentro del proyecto de R en el que vayamos a trabajar.

En este caso se utilizan los archivos .sav para importar los datos. Aunque estos están disponibles en formato .csv y este es un formato abierto y de texto plano1 es preferible la versión .sav porque contiene todos los metadatos de la base, incluyendo códigos correctamente ordenados de las variables categóricas y etiquetas de las variables.

Ambas bases están muy limpias, sin ambigüedades en la codificación ni errores de ortografía. Esto puede parecer obvio, pero no lo es.

Importación

#### MUY IMPORTANTE ####
#### Modificar el path relativo a la carpeta del proyecto en su computadora ####

#base de hogares
hogares <- read_sav("../../static/docs/datos/ENES_Hogares_version_final.sav")

#base de personas
personas <- read_sav("../../static/docs/datos/ENES_Personas_version_final.sav")

Diccionario de variables

Los nombres de las variables son cortos y fáciles de manejar en R o cualquier otro software en el que usamos un script o consola como forma de acceder a los datos. Sin embargo a menos que estemos muy familiarizados con estos nombres será difícil recordar a que pregunta del cuestionario corresponden. Lo mismo si queremos comunicar los resultados de un análisis de estos datos. Es buena idea crear un diccionario de variables: una estructura de datos relacional que vincule a los nombres cortos de las variables con su definición larga. Para eso se crean dos diccionarios de variables, uno por cada base. Al ser objetos de la clase data.frame podemos verlos y explorarlos con la función View() o directamente usarlos en el código para renombrar las variables.

La función renombrar() utiliza al diccionario de variables para cambiar los nombres cortos por los nombres largos cuando es necesario. Esta función recibe como input un data.frame y regresa otro data.frame en el que solo cambian los nombres. Por lo tanto no es necesario iterarla explícitamente a todas las columnas y funciona sin problemas con el operador %>%.

diccionario_hogares <- tibble(nombre = names(hogares), 
                                etiqueta = map_chr(hogares, attr, "label"))
diccionario_personas  <- tibble(nombre = names(personas), 
                                etiqueta = map_chr(personas, attr, "label"))
diccionario <- bind_rows(diccionario_hogares, diccionario_personas)

# Función renombrar
# Requiere nombres fijos de diccionario y columnas!

renombrar <- function(x) {
  rename_all(x, ~diccionario$etiqueta[match(., diccionario$nombre)])
}

# Para ver el diccionario quite el símbolo # de la siguiente línea y ejecútela
# View(diccionario)

Unión de las bases de datos

Por diseño los datos se ubican en dos bases, una con atributos de los hogares y otra con atributos de las personas. Dado que todas las personas encuestadas pertenecen a alguno de los hogares y que los códigos de vivienda y hogar están presentes en las dos bases de datos es posible hacer un join y reunir toda la información.

Obtendremos una base de datos en la que cada fila será una persona (n=27610). Evitar confusiones con la unidad de análisis en cada caso corre por cuenta de quién analice la base de datos. Valga recordar que no es lo mismo habitar una vivienda con techo de chapas que tener techo de chapas.

unida <- left_join(personas, hogares, by = c("nocues", "nhog")) %>% 
  rename(fcalib_hog = f_calib3.y, 
         fcalib_per = f_calib3.x)
## Warning: Column `nocues` has different attributes on LHS and RHS of join
## Warning: Column `nhog` has different attributes on LHS and RHS of join

Estadísticos descriptivos: proporciones

Proporción de personas entrevistadas por sexo

La primera tabla que realizaremos utiliza información sobre las personas encuestadas. Dicho de otro modo, no buscamos inferir un parámetro de la población de la que proviene la muestra ni utilizamos el ponderador muestral para corregir sesgos de selección por diseño o problemas de no respuesta. Por lo tanto las proporciones serán proporciones de personas a las que se aplicó la entrevista. Más adelante buscaremos soluciones para ambos problemas.

Usando la función count() obtenemos tablas de frecuencias en forma “largo”: una o más columnas indican el grupo sobre el que se calculó la frecuencia y la columna n indica la frecuencia calculada. En este caso (univariado) este formato es obvio al punto de parecer natural. Sin embargo veremos que para tablas de más de una dimensión diverge del formato más habitual de la tabla de contingencia. De todos modos podemos pasarlo a a tabla de contingencia en caso de ser necesario.

personas %>% 
  select(v109) %>% 
  as_factor() %>%    #La paso desde numérica etiquetada a factor
  count(v109) %>%    #Indico la variable a contar
  mutate(prop = n / sum(n))  #Agrego una columna con las proporciones
## # A tibble: 3 x 3
##   v109      n     prop
##   <fct> <int>    <dbl>
## 1 Varón 13258 0.480   
## 2 Mujer 14346 0.520   
## 3 Otro      6 0.000217

Proporción de entrevistas por sexo y estado civil

En este caso obtenemos las frecuencias condicionales de dos variables: sexo y una pregunta sobre si la persona entrevistada planchó o no planchó ropa la semana pasada.

Modificamos levementa la sintaxis anterior:

  1. Renombramos las variables para aprovechar las etiquetas largas
  2. En lugar de definir al grupo para las frecuencias en las llamada misma a count() lo definimos previamente con group_by_all(). Este atajo permite definir grupos para todas las variables disponibles. NUNCA usarlo sin hacer previamente un subconjunto de variables con select().
  3. Pasamos la tabla a formato “ancho”, ubicando a las categorías de una variable como filas y las categorías de la otra como columnas.
  4. Usamos la función kable() para mejorar el formato de salida de la tabla.
personas %>% 
  select(v109, v154) %>% 
  renombrar() %>% 
  as_factor() %>% 
  group_by_all() %>% 
  count() %>% 
  spread(Sexo, n, fill = 0) %>% 
  knitr::kable(caption = "Tareas del hogar y género")
## Warning: Factor `Planchar durante la semana pasada` contains implicit NA,
## consider using `forcats::fct_explicit_na`

## Warning: Factor `Planchar durante la semana pasada` contains implicit NA,
## consider using `forcats::fct_explicit_na`

## Warning: Factor `Planchar durante la semana pasada` contains implicit NA,
## consider using `forcats::fct_explicit_na`
Table 1: Tareas del hogar y género
Planchar durante la semana pasada Varón Mujer Otro
1864 7357 2
No 10325 5898 4
NA 1069 1091 0

Los resultados, lamentablemente, sorprenden poco. Más allá de la interpretación de la tabla ha emergido un dato técnico de las variables. La función count() emite unas advertencias algo extrañas:

1: Factor `Planchar durante la semana pasada` contains implicit NA, consider using `forcats::fct_explicit_na` 

Simplemente nos advierte que una de las variables (Planchar durante la semana pasada) contiene casos perdidos (missing), que en R se codifican como NA. No sabemos mucho sobre el orígen de esos missing, pero deberemos tomar una decisión: los consideramos una categoría de respuesta en sí misma (hacerlos explícitos) o los eliminamos de la base de datos.2

Seguiremos la práctica utilizada por autores y autoras del libro “Cómo somos, vivimos y convivimos en una sociedad desigual” y eliminaremos los missing con drop_na().

personas %>% 
  select(v109, v154) %>% 
  renombrar() %>% 
  as_factor() %>% 
  drop_na() %>% 
  group_by_all() %>% 
  count() %>% 
  
  #Pasar a formato ancho para facilitar la lectura
  
  spread(key = Sexo, value = n, fill = 0) %>% 
  knitr::kable(caption = "Tareas del hogar y género sin missing")
Table 2: Tareas del hogar y género sin missing
Planchar durante la semana pasada Varón Mujer Otro
1864 7357 2
No 10325 5898 4

Uso del ponderador muestral

El segundo ejercicio de manejo consistente en replicar la tabla 7.9 del libro “Cómo somos, vivimos y convivimos en una sociedad desigual”. Corresponde al capítulo 7 del libro, “Trayectorias y capitales educativos”, de Carina Kaplan y Juan Ignacio Piovani.

Dicha tabla presenta las proporciones de conocimiento de idiomas extranjeros de la población de 30 o más años por regiones, total nacional y CABA. Nos servirá para familiarizarnos con la base de datos, los nombres de columnas y para validar el funcionamiento del ponderador muestral. Dado que los datos que presenta no se encuentran todos en el mismo nivel de jerarquía es necesario elaborar tres tablas: una nacional, otra por regiones y una última para el aglomerado correspondiente a CABA. En términos estrictos son tres tablas presentadas en una misma tabla.

Esta tabla incorpora en el cálculo a factor de calibración. Dicho factor otorga un peso diferente a cada fila de la base de datos, corrigiendo efectos de diseño muestral (aglomerados con probabilidad variables de selección) así como problemas ocasionados por no respuesta. La columna f_calib3 de ambas bases de datos incluye controles para tres tipos de sesgo:

  1. De diseño: los aglomerados tienen probabilidades variables de selección, esta es más alta en los aglomerados pequeños.
  2. Sesgo de no respuesta. La no respuesta no fue homogénea en los diferentes radios.
  3. Ajuste por estructura de sexo y edad de acuerdo a datos censales y proyecciones.

Quienes diseñaron la encuesta consideran imprescindible utilizar el ponderador muestral para comparaciones y generalizaciones.

Proporciones de conocimiento de idioma extranjero - Nivel Nacional

Este es el caso más simple, ya que calcularemos las frecuencias de una sola variable. Sin embargo es necesario incluir otras dos en los datos que utilizaremos: la edad para poder aplicar el filtro de mayores de 29 años y f_calib3, la columna del data.frame personas en la que se ubica el ponderador muestral.

Procedimiento:

  • seleccionar las variables de interés
  • filtrar las filas con edades mayores o iguales a 30 años
  • eliminar los missing de la base de datos
  • recodificar la variable v118a compactando a las categorías “Sí, nivel avanzado” y “Sí, bilingüe” en la nueva categoría “Avanzado o bilingüe”. Para mantener los nombres idénticos a la tabla 7.9 recodificamos “Sin conocimiento” como “No”.
  • contar utilizando el ponderador muestral como argumento wt= en la función count()
  • Calcular proporciones por cada nivel conocimiento de idioma extranjero
personas %>% 
  select(v118a, f_calib3, v108) %>% 
  filter(v108 >= 30) %>% 
  drop_na %>% 
  as_factor() %>% 
  mutate(v118a = fct_recode(v118a, "Avanzado o bilingüe" = "Sí, nivel avanzado", 
                            "Avanzado o bilingüe" = "Sí, bilingüe",
                            "Sin conocimiento" = "No")) %>% 
  count(v118a, wt = f_calib3) %>% 
  mutate (Nacional = n/sum(n)) %>% 
  select(-n) -> Nacional

Nacional
## # A tibble: 4 x 2
##   v118a               Nacional
##   <fct>                  <dbl>
## 1 Sin conocimiento      0.727 
## 2 Sí, nivel básico      0.178 
## 3 Sí, nivel medio       0.0505
## 4 Avanzado o bilingüe   0.0450

Proporciones de conocimiento de idioma extranjero por regiones

En este caso calculamos la proporción de personas por categoría de conocimiento de idioma extranjero dentro de cada región.

El procedimiento es el mismo que en el anterior, excepto que que utilizamos a las dos variables en group_by() previo al conteo y luego definimos un grupo por región para el cálculo de las proporciones.

spread() se encarga de pasar del formato “largo” de tríos de claves y valores al formato propiamente tabular.

personas %>% 
  select(v118a, region, f_calib3, v108) %>% 
  filter(v108 >= 30) %>% 
  drop_na %>% 
  as_factor() %>% 
  mutate(v118a = fct_recode(v118a, "Avanzado o bilingüe" = "Sí, nivel avanzado", 
                            "Avanzado o bilingüe" = "Sí, bilingüe",
                            "Sin conocimiento" = "No")) %>% 
  group_by(v118a, region) %>%
  count(wt = f_calib3) %>% 
  group_by(region) %>% 
  mutate(prop = n/sum(n)) %>% 
  select(-n) %>% 
  spread(region, prop) %>% 
  #Una expresión regular para eliminar el texto entre paréntesis de los nombres de variable
  rename_all(str_remove, " \\(([^\\)]+)\\)") -> por_region

por_region
## # A tibble: 4 x 8
##   v118a     `Gran Buenos Ai…   Cuyo Pampeana Centro    NEA    NOA Patagonia
##   <fct>                <dbl>  <dbl>    <dbl>  <dbl>  <dbl>  <dbl>     <dbl>
## 1 Sin cono…           0.691  0.792    0.704  0.712  0.797  0.805     0.760 
## 2 Sí, nive…           0.173  0.148    0.200  0.216  0.125  0.151     0.161 
## 3 Sí, nive…           0.0697 0.0294   0.0549 0.0398 0.0410 0.0280    0.0363
## 4 Avanzado…           0.0667 0.0304   0.0415 0.0327 0.0373 0.0165    0.0430

Proporciones de conocimiento de idioma extranjeo (CABA)

El caso de CABA requiere que filtremos la base de datos y dejemos solamente aquellas filas en las que el aglomerado es CABA.

personas %>% 
  select(v118a, aglo, f_calib3, v108) %>% 
  filter(v108>=30) %>% 
  as_factor() %>% 
  filter(aglo == "CABA") %>% 
  mutate(v118a = fct_recode(v118a, "Avanzado o bilingüe" = "Sí, nivel avanzado", 
                            "Avanzado o bilingüe" = "Sí, bilingüe",
                            "Sin conocimiento" = "No")) %>% 
  count(v118a, wt = f_calib3) %>% 
  mutate (CABA = n/sum(n)) %>% 
  select(-n) -> CABA

Unir las tablas

Como las tres tablas tienen en común la columna v118a es posible hacer un join para unir las tres estructuras en una sola.

list(CABA, por_region,  Nacional) %>% 
  reduce(left_join) -> tabla7.9
## Joining, by = "v118a"
## Joining, by = "v118a"
## Warning: Column `v118a` has different attributes on LHS and RHS of join
tabla7.9 %>% 
  mutate_if(is.numeric, scales::percent) %>% 
  knitr::kable(caption = "Conocimiento de idiomas extranjeros en la población de 30 años o más (en porcentajes). Total nacional, CABA y regiones (Replicación)")
Table 3: Conocimiento de idiomas extranjeros en la población de 30 años o más (en porcentajes). Total nacional, CABA y regiones (Replicación)
v118a CABA Gran Buenos Aires Cuyo Pampeana Centro NEA NOA Patagonia Nacional
Sin conocimiento 56.1% 69.1% 79.2% 70.4% 71.2% 79.7% 80.5% 76.0% 72.7%
Sí, nivel básico 18.4% 17.3% 14.8% 20.0% 21.6% 12.5% 15.1% 16.1% 17.8%
Sí, nivel medio 11.8% 7.0% 2.9% 5.5% 4.0% 4.1% 2.8% 3.6% 5.1%
Avanzado o bilingüe 13.7% 6.7% 3.0% 4.1% 3.3% 3.7% 1.7% 4.3% 4.5%

El resultado replica exactamente el reportado en la tabla 7.9 del libro.

Gráfico de proporciones

Los datos de la Tabla 7.9 se pueden representar facilmente en un gráfico de barras apiladas. Se utiliza una paleta de colores de alto contraste y apta para personas con la mayoría de los tipos de daltonismo.

tabla7.9 %>% 
  gather(variable, valor, -v118a) %>% 
  mutate(variable = fct_relevel(variable, "Nacional"), 
         variable = fct_recode(variable, "GBA" = "Gran Buenos Aires")) %>% 
  ggplot(aes(x=variable, y = valor, fill = v118a)) + 
  geom_col() + 
  theme_minimal() + 
  labs(fill = "Lengua extranjera", 
       y = NULL, 
       x = "Región", 
       title = "Concentración de ventajas") + 
  theme(#axis.text.y = element_blank(), 
        legend.position = "bottom") + 
  scale_fill_viridis_d() + 
  scale_y_continuous(labels = scales::percent)

Incertidumbre en la estimación

La tabla 7.9 reporta las proporciones encuestados/as ponderados por conocimiento de idioma extranjero. En sentido estadístico se trata de un estimador puntual de proporción. Sin embargo, por tratarse de datos obtenidos de una muestra (aún una tan grande y bien diseñada como la de la ENES) ese estimador puntual es eso: una estimación de la proporción poblacional, que en realidad es desconocida. Nunca podremos saber con absoluta certeza cuál es, sin embargo con una muestra aleatoria como la que estamos utilizando, es posible cuantificar la incertidumbre de la estimación que estamos realizando.

Siguiendo a la literatura contemporánea sobre el tema (Lumley, 2010; Lumley y Scott, 2017) se aplicará el método bootstrap para el cálculo de intervalos de confianza de la estimación de proporciones y la visualización de la distribución de las proporciones replicadas para dar cuenta de la incertidumbre en la estimación.

El método bootstrap (Efron, 1979) es un método sumamente simple, intuitivo y robusto para la inferencia estadística. Consiste en replicar \(R\) veces el cálculo de los estadísticos, remuestreando con reemplazo las filas de la base de datos en cada replicacion. Asumiendo que cada dato remuestreado al azar correspondena una de las posibles muestras aleatorias que podríamos haber obtenido originalmente los estadísticos que de ellos calculamos son también posibles estadísticos provenientes de la población. Al repetir el proceso podemos identificar cuales de esos estadísticos son los más probables. Aunque el procedimiendo es no paramétrico y no impone supuestos distribucionales a medida que aumenta el número de replicaciones la distribución bootstrap del estadístico converge con una distribución normal.3. Así podemos aprovechar las muy amables características de esta distribución para estimar intervalos de confianza o calcular p-value de algún estadístico.

No aplicaremos el bootstrap un bootsprap completo, remuestreando todas las posibles permutaciones de muestras con reemplazo. Está demostrado por simulaciones que una aproximación Monte Carlo es más que suficiente suficiente. En este caso replicaremos 10 000 veces el remuestreo al azar simple con reemplazo.

El procedimiento es simple: utilizamos el mismo código con el que calculamos las proporciones originalmente, agregando una función que aleatoriza con reemplazo a las filas de la base de datos. Ubicamos a esa macro función dentro de la función rerun(), que simplemente repite la operación \(R\) veces y organiza el resultado en una lista.4

Bootstrap de proporciones de conocimiento idioma extranjero por sexo

El primer caso que tomaremos es el de la distribución de conocimiento de idioma extranjero por sexo. A modo de referencia comenzaremos calculando las proporciones por grupos con los datos tal como están en la base. Es decir, calculando es estimador puntual de proporciones.

# Preparación de los datos

personas %>% 
  select(v118a, region, f_calib3, v108, v109) %>% 
  filter(v108 >= 30) %>% 
  drop_na %>% 
  as_factor() %>% 
  mutate(v118a = fct_recode(v118a, "Avanzado o bilingüe" = "Sí, nivel avanzado", 
                            "Avanzado o bilingüe" = "Sí, bilingüe",
                            "Sin conocimiento" = "No")) %>% 
  select(-v108) -> para_bootstrap
para_bootstrap %>% 
  filter ( v109 != "Otro") %>% 
  group_by(v109) %>%
  count(v118a, v109, wt = f_calib3) %>% 
  group_by(v109) %>% 
  mutate(prop = n/sum(n), 
         prop = scales::percent(prop)) %>% 
  select(-n) %>% 
  spread(v109, prop) %>% 
  knitr::kable(caption = "Estimador puntual de proporciones de conocimiento de idioma extranjero por sexo")
Table 4: Estimador puntual de proporciones de conocimiento de idioma extranjero por sexo
v118a Varón Mujer
Sin conocimiento 73.6% 71.9%
Sí, nivel básico 17.2% 18.2%
Sí, nivel medio 5.4% 4.7%
Avanzado o bilingüe 3.8% 5.1%

Una lectura precipitada de esta tabla nos llevaria a pensar que, aunque pequeñas, hay diferencias entre las proporciones de hombres y mujeres en todos los niveles de conocimiento de idioma extranjero. Esto es verdadero para la muestra, pero no sabemos si lo es para la población de la que seleccionamos la muestra. Si el azar hubiera seleccionado otros hogares bien podríamos tener otras proporciones. El método bootstrap nos ayuda a cuantificar la probabilidad de que en una muestra al azar obtengamos una diferencia como la que estamos observando en la tabla. Este procedimiento es intrínsecamente incierto, por eso prefiero hablar de cuantificar la incertidumbre más que poner a prueba una hipótesis. La afirmación que hagamos sobre la diferencia de proporciones depende de los números que da el bootstrap, pero sobre todo de nuestra tolerancia a la incertidumbre.

# Replicaciones bootstrap

rerun(10000, 
para_bootstrap %>% 
          sample_frac(size = 1,     
                      replace = TRUE) %>% 
  group_by(v109) %>%
  count(v118a, v109, wt = f_calib3) %>% 
  mutate(prop = n /sum(n)) ) -> boot_idiomas_sexo

Con las replicaciones realizadas podemos explorar la distribución de las proporciones. Visualmente un histograma presenta nos permite dar cuenta de la variabilidad de las proporciones estimadas en las replicaciones, así como valorar visualmente si hay una diferencia significativa de en las proporciones poblacionales en alguna de las categorías.

Nótese que cada uno de los subgráficos tiene su propia escala en el eje \(x\). Se omite la etiqueta del eje \(y\) por tener poca relevancia. Su escala depende de una decisión arbitraria: el número de replicaciones.

boot_idiomas_sexo %>% 
  bind_rows() %>% 
        filter(v109 != "Otro") %>% 
    ggplot(aes(x=prop, fill = v109)) +
      geom_histogram(position = "dodge", bins = 150) + 
      facet_wrap(~v118a, scales = "free") +  
      theme_minimal() + 
  theme(legend.position = "bottom", 
        axis.text.y = element_blank()) + 
  scale_x_continuous(labels = scales::percent) + 
  scale_fill_viridis_d() +
  labs(title = "Distribución bootstrap de proporciones", 
       fill = "Sexo", 
       y = NULL, 
       x = NULL)

En todos los casos encontramos una distribución simétrica y muy concentrada en torno a la media. Podemos esperar intervalos de confianza estrechos.

Estos gráficos tienen una interpretación muy directa. Si las “campanas” de barras amarillas y violetas estuvieran completamente superpuestas interpretaríamos que no hay diferencias en la proporción de conocimiento de idioma extranjero entre varones y mujeres.

Si estuvieran completamente separadas interpretaríamos que hay una diferencia en las proporciones a nivel poblacional. Es decir, que la diferencia de proporciones en el estimador puntual no es un caso aislado, producto del azar que nos dió una mano mala. Sacando casos muy poco frecuentes o con datos simulados lo usual es que haya un poco de superposición entre las campanas: esa región entre los “picos” de las campanas en la que hay barras amarillas y violetas. Tal es el caso de las categorías “Sin conocimiento”, “Sí, nivel básico” y “Sí, nivel intermedio”. En muchas de las muestras replicadas por bootstrap la proporción de hombres es mayor que la de mujeres y en muchas otras obtenemos opuesto resultado. No podemos afirmar que no haya una diferencia, pero tampoco que la haya. Al menos no con el intrumento con el que hemos medido. Cualquiera de las afirmaciones tendría un nivel inaceptablemente alto de incertidumbre y en esos casos la costrumbre es aceptar la hipótesis de nulidad: no hay diferencia.

El caso de “Avanzado o bilingüe” es diferente. Hay una zona en la que las barras se superponen, pero es pequeña. Sin omitir que existe una probabilidad mayor que 0 de que en la población las proporciones sean iguales es muy razonable afirmar que hay más mujeres que hombres con conocimientos avanzados de un idioma extranjero o que son directamente bilingües. Lo sabemos porque en muy pocas replicaciones obtuvimos el resultado inverso.

boot_idiomas_sexo %>% 
  bind_rows() %>% 
      filter(v109 != "Otro") %>% 
  group_by(v118a, v109) %>% 
  summarise(perc1 = quantile(prop, probs = 0.025), 
            perc99  = quantile(prop, probs = 0.975))  %>% 
  mutate_at(vars(perc1, perc99), scales::percent) %>% 
  unite(intervalo, perc1, perc99, sep = " - ") %>% 
  spread(v109, intervalo) %>% 
  knitr::kable()
v118a Varón Mujer
Sin conocimiento 71.85% - 75.25% 70.44% - 73.46%
Sí, nivel básico 15.73% - 18.815% 16.88% - 19.593%
Sí, nivel medio 4.632% - 6.323% 4.044% - 5.428%
Avanzado o bilingüe 3.14% - 4.47% 4.38% - 5.93%

Conocimiento de idioma extranjero. Intervalos de confianza.

En este último caso indagamos sobre las proporciones de conocimiento de idioma extranjero por región. El procedimiento de replicación es el mismo, la diferencia en es que en lugar de presentar la información sobre la incertidumbre de la estimación en forma gráfica lo haremos a través de intervalos de confianza. Aprovechando la distribución aproximadamente normal del bootstrap, la forma más simple obtener estos intervalos es reportar los cuantiles 0.025 y 99.75 de las proporciones replicadas.

rerun(10000, 
para_bootstrap %>% 
          sample_frac(size = 1,     
                      replace = TRUE) %>% 
  count(v118a, region, wt = f_calib3) %>% 
  group_by(region) %>% 
  mutate(prop = n /sum(n)) ) -> boot_idiomas_region

boot_idiomas_region%>% 
  bind_rows() %>% 
  group_by(region, v118a) %>% 
    summarise(perc1 = quantile(prop, probs = 0.025), 
            perc99  = quantile(prop, probs = 0.975))  %>% 
  mutate_if(is.numeric, scales::percent) %>% 
  unite(intervalo, c(perc1, perc99), sep = " - ") %>% 
  spread(v118a, intervalo) %>% 
  ungroup() %>% 
  mutate(region = str_remove(region, " \\(([^\\)]+)\\)")) %>% 
  knitr::kable(caption = "Conocimiento de idioma extranjero por región. Intervalo de confianza al 99%")
## `mutate_if()` ignored the following grouping variables:
## Column `region`
Table 5: Conocimiento de idioma extranjero por región. Intervalo de confianza al 99%
region Sin conocimiento Sí, nivel básico Sí, nivel medio Avanzado o bilingüe
Gran Buenos Aires 66.8% - 71.3% 15.4% - 19.2% 5.8% - 8.1% 5.5% - 7.9%
Cuyo 76.8% - 81.5% 12.8% - 17.1% 2.1% - 3.9% 2.2% - 4.0%
Pampeana 66.9% - 73.7% 16.9% - 23.2% 4.0% - 7.2% 2.9% - 5.6%
Centro 68.6% - 73.7% 19.1% - 24.1% 3.1% - 5.0% 2.5% - 4.2%
NEA 77.0% - 82.3% 10.4% - 14.7% 2.9% - 5.5% 2.6% - 5.0%
NOA 78.2% - 82.6% 13.3% - 17.0% 1.7% - 4.1% 0.9% - 2.6%
Patagonia 72.9% - 78.9% 13.5% - 18.7% 2.5% - 4.9% 2.9% - 5.9%

Hay diferencias importantes en todas las categorías de conocimiento de idioma extrajero, sobre todo si tomamos como referencia al Gran Buenos Aires.5 Tiene la proporción más alta de personas con nivel avanzado o bilingüe y una de las mas bajas de personas en la categoría “Sin conocimientos”. Al mismo tiempo sabemos que en esa región los niveles educativos agregados son más altos que en las demás y que el nivel educativo a su vez está relacionado con el nivel de conocimiento de idioma extranjero. Quizas la diferencia que observamos en los niveles de conocimiento de idioma extranjero pueda ser atribuida a la distribución desigual de las personas por nivel educativo en las regiones. Para responder esta pregunta es necesario utilizar alguna herramienta más sofisticada que las tablas de contingencia. En la próxima entrada buscaremos una respuesta a esta pregunta ajustando un modelo de regresión lineal a los datos de las ENES.

Bibliografía

  • Efron, B. (1979). Bootstrap methods: another look at the jackknife. The Annals of Statistics. 7 (1): 1–26.
  • Lumley, T. (2010). Complex surveys: A guide to analysis using R. Wiley.
  • Lumley, T. & Scott, A. (2017). Fitting regression models to survey data. Statistical Science, 32 (2), 265-278

  1. vs. propietario y binario, como en el caso de SPSS

  2. Eliminar los casos perdidos puede introducir un sesgo en las estimaciones si estos no están distribuidos de manera completamente aleatoria. Verificar el cumplimiento de este supuesto es prácticamente imposible.

  3. Ninguna sopresa, el teorema central del límite es el teorema central del límite.

  4. En R hay muchas funciones y librerías para aplicar bootstrap, pero tienen unas interfaces complicadas. Así que prefiero escribir una función que realiza las replicaciones.

  5. Y más aún si tomamos como referencia a la CABA.