Introducción
Las bases de datos de la ENES tienen abundante información sobre las personas y los hogares en los que esas personas viven o vivieron. Muchas preguntas de interés sociológico sobre la transmisión de las desigualdades requieren este tipo de datos. En este caso trabajaremos con una pregunta muy simple ¿Cómo es la relación entrenivel educativo de una persona y el nivel educativo del Principal Sustento del Hogar (PSH) en el que vivió? Una forma de responderla es creando una tabla de contingencia en cuyas filas se ubique el nivel educativo de la persona y en las columnas el nivel educativo del PSH del hogar en el que vive/vivió. En apariencia esto es simple, la complicaciones comienzan cuando verificamos que en la base de datos no tenemos una variable que registre el nivel educativo del PSH de cada persona. La información está, solo que dispersa en múltiples variables y es necesario reunirla. Esta entrada se enfoca en el proceso de manejo de datos para crear la variable nivel_ed_psh
, en la que se registra el máximo nivel educativo alcanzado por el Principal Sustento del Hogar del hogar en el que esa persona vive o vivió. Lo haremos creando bases de datos parciales en las que se lleva a cabo la imputación de la variable según aplique y en el uso de joins por claves para reunir toda la información al final.
El problema
La variable nivel_ed_psh
no existe, pero la información para crear está disponible.
Para PSH y cónyugue de PSH hay una medición directa. En la base de datos de hogares las variables
v241a
yv244a
reportan el máximo nivel educativo alcanzado PSH y cónyugue respectivamente. La columnav111
de la base de datos personas clasifica a las peronas por Parentesco con el PSH, por lo que podemos usarla para filtrar estos casos.Para quienes no son PSH o cónyugue de PSH no tenemos esta información directamente consignada. Sin embargo sabemos que cada persona pertenece a un hogar y podemos identificar al PSH de ese hogar y consultar el máximo nivel educativo de esa persona en la variable
nivel_ed
. Así imputamos un valor de nivel educativo del PSH para sus hijos/hijas, hijastros y hijastras. Los valores que obtenemos no son exactamente los mismos que en el caso anterior, ya que las preguntasv241a
yv244a
registran en máximo nivel educativo del PSH a los 15 años de edad de la persona. En esta imputación por hogar las edades de las personas no son necesariamente 15 años al registro de la escolaridad del PSH, en realidad es la edad que tienen al momento de la encuesta. Esta situación no es la ideal, pero son los datos que hay.En el caso de nietos se imputará también el nivel educativo del PSH del hogar. Esto es consistente con la forma en la que está medida las variables
v241a
yv244a
que usamos como referencia. Es decir, el análisis subsiguiente no será sobre movilidad educativa entre padres/madres e hijos/hijas, sino entre el nivel educativo del PSH del hogar orígen y la persona al momento de la encuesta.Con el objetivo de ampliar tanto como sea posible al imputación de esta variable para adultos se imputará a quienes tienen relación de parentesco “Hermano/a” de PSH el mismo nivel educativo del PSH de orígen del PSH actual. En términos prácticos, si un PSH indica que a los 15 años el PSH del hogar en el que vivía tenía educación primaria a su hermano/a se le inputará el mismo valor. Se asume, por lo tanto, que vivían en el mismo hogar, aún cuando pudiera no ser el caso.
Enfoque del problema
Se enfoca el problema como un problema de imputación selectiva por subconjuntos. Para cada categoría de parentesco registrada en v111
se buscará una solución ad hoc. Resuelto el problema para cada subconjunto estos se reúnen en una sola tabla y se unen con el resto de los datos de la base personas
con un join que usa las variables clave nocues
, nhog
y miembro
. Estas variables permiten identificar a cada individuo.
Carga de datos
library(tidyverse)
library(haven)
library(tidyverse)
# 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")
# base unida de personas y hogares
unida <- left_join(personas, hogares, by = c("nocues", "nhog")) %>%
rename(fcalib_hog = f_calib3.y,
fcalib_per = f_calib3.x)
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)
renombrar <- function(x) {
rename_all(x, ~diccionario$etiqueta[match(., diccionario$nombre)])
}
Diagnóstico de los datos
Antes de comenzar con las operaciones de imputación es buena idea saber qué esperamos del resultado. Como la imputación se hará por grupos de relación de parentesco con PSH vamos a contar cuantas filas son imputables (por pertenecer a los grupos de parentesco en los que tenemos información) y cuantas inimputables. No utilizaremos el ponderador muestral, aquí nos interesan los datos de encuestados y encuestadas.
\(n\) por relación de parentescto
# Una lista de listas de recodificación, más adelante agregaremos elementos.
reco <- list(
imputabilidad = list(
imputables = c("PSH", "Cónyuge",
"Hijo/a (incluye hijastro/a)",
"Hermano/a", "Nieto/a"),
inimputables = c("Yerno/Nuera", "Cuñado/a",
"Padre/Madre/Suegro/Suegra", "Otros familiares",
"Servicio doméstico", "Otros no familiares") )
)
personas %>%
select(v111) %>%
count(v111) %>%
as_factor() %>%
knitr::kable(caption = "Frecuencias de relación de parentesco con PSH")
v111 | n |
---|---|
PSH | 8265 |
Cónyuge | 5093 |
Hijo/a (incluye hijastro/a) | 11274 |
Yerno/Nuera | 259 |
Hermano/a | 327 |
Nieto/a | 1283 |
Cuñado/a | 53 |
Padre/Madre/Suegro/Suegra | 599 |
Otros familiares | 348 |
Servicio doméstico | 8 |
Otros no familiares | 101 |
personas %>%
select(v111) %>%
as_factor() %>%
mutate(imputabilidad = fct_collapse(v111, !!!reco$imputabilidad)) %>%
count(imputabilidad) %>%
mutate(proporción = n / sum(n)) %>%
knitr::kable(caption = "Proporción de n imputable")
imputabilidad | n | proporción |
---|---|---|
imputables | 26242 | 0.9504527 |
inimputables | 1368 | 0.0495473 |
Con este procedimiento potencialmente tenemos datos para imputar un 95% de la n. Digo potencialmente porque podrían haber información faltante que reduzca este número, pero es un buen punto de partida. A pesar de una proporción alta hay algunos sesgos que podrían introducirse al hacer esta selecció. Es esperable que los imputados sean un poco más jóvenes que el total, porque no se imputan Madre/Padre de PSH.
Nivel máximo de escolaridad de PSH de hijos/as en el hogar al momento de la entrevista
Pasos:
- Crear una tabla con la escolaridad de PSH por hogar
- Filtrar en la tabla
personas
a hijes y nietes de PSH - Join izquierdo por tabla 2, agregando el dato de escolaridad de PSH correspondiente.
left_join(
personas %>%
select(nocues, nhog, miembro, v111) %>%
filter(v111 %in% c(3, 7)),
unida %>%
select(nocues, nhog, v111, nivel_ed) %>%
filter(v111 == 1),
by = c("nocues", "nhog")) %>%
select(nocues, nhog, miembro, parentesco = v111.x, niveled_psh = nivel_ed) %>%
as_factor() ->
niveled_PSH_hijesnietes
# Resultado
niveled_PSH_hijesnietes
## # A tibble: 12,557 x 5
## nocues nhog miembro parentesco niveled_psh
## <dbl> <dbl> <dbl> <fct> <fct>
## 1 1 1 3 Hijo/a (incluye hijastro/a) Universitario incompleto
## 2 1 1 5 Nieto/a Universitario incompleto
## 3 3 1 6 Hijo/a (incluye hijastro/a) Secundario/Polimodal comple…
## 4 4 1 3 Hijo/a (incluye hijastro/a) Secundario/Polimodal comple…
## 5 4 1 4 Hijo/a (incluye hijastro/a) Secundario/Polimodal comple…
## 6 4 1 5 Hijo/a (incluye hijastro/a) Secundario/Polimodal comple…
## 7 5 1 4 Hijo/a (incluye hijastro/a) Primaria/EGB completo
## 8 5 1 5 Hijo/a (incluye hijastro/a) Primaria/EGB completo
## 9 6 1 3 Hijo/a (incluye hijastro/a) Primaria/EGB completo
## 10 6 1 4 Hijo/a (incluye hijastro/a) Primaria/EGB completo
## # … with 12,547 more rows
Nivel máximo de escolaridad de PSH de PSH
Este caso es relativamente simple, se filtra a “PSH” y “Hermano/a” y se toma el valor de la variable v241a
como niveled_psh
.
unida %>%
select(nocues, nhog, miembro, v111, v240a ) %>%
as_factor() %>%
filter(v111 %in% c("PSH", "Hermano/a")) %>%
rename(niveled_psh = v240a, parentesco = v111) %>%
as_factor() -> niveled_PSH_PSH_o_hermano
Nivel máximo del PSH del cónyugue del PSH
Igual al anterior.
unida %>%
select(nocues, nhog, miembro, v111, v244a ) %>%
as_factor() %>%
filter(v111 == "Cónyuge") %>%
rename(niveled_psh = v244a, parentesco = v111) -> niveled_PSH_cónyuge
Variable imputada
Se crea un data.frame con 4 variables: nocues
, nhog
y miembro
para identificación y join con las demás bases de datos y la variable imputada niveled_psh
con la información nueva. La variable niveled_psh
tiene casos perdidos (NA
). Para evitar ulteriores confusiones se los explicita en la categoría Sin información
.
niveled_psh <- bind_rows(niveled_PSH_hijesnietes,
niveled_PSH_PSH_o_hermano,
niveled_PSH_cónyuge) %>%
mutate(niveled_psh = fct_explicit_na(niveled_psh , "sin_información"))
niveled_psh
## # A tibble: 26,242 x 5
## nocues nhog miembro parentesco niveled_psh
## <dbl> <dbl> <dbl> <fct> <fct>
## 1 1 1 3 Hijo/a (incluye hijastro/a) Universitario incompleto
## 2 1 1 5 Nieto/a Universitario incompleto
## 3 3 1 6 Hijo/a (incluye hijastro/a) Secundario/Polimodal comple…
## 4 4 1 3 Hijo/a (incluye hijastro/a) Secundario/Polimodal comple…
## 5 4 1 4 Hijo/a (incluye hijastro/a) Secundario/Polimodal comple…
## 6 4 1 5 Hijo/a (incluye hijastro/a) Secundario/Polimodal comple…
## 7 5 1 4 Hijo/a (incluye hijastro/a) Primaria/EGB completo
## 8 5 1 5 Hijo/a (incluye hijastro/a) Primaria/EGB completo
## 9 6 1 3 Hijo/a (incluye hijastro/a) Primaria/EGB completo
## 10 6 1 4 Hijo/a (incluye hijastro/a) Primaria/EGB completo
## # … with 26,232 more rows
Unión con el resto de los datos
Como el data.frame niveled_psh
tiene las columnas de identificación de vivienda, hogar y miembro es muy fácil unirlo con la base de datos de personas. Simplemente hacemos un join por el lado izquierdo en el que obtendremos todas las filas de la base de datos personas y se rellenará con NA
(missing) cuando no hay información sobre el nivel educativo del PSH.
left_join(personas, niveled_psh) %>%
count(niveled_psh, sort = TRUE) %>%
mutate(cat = 1:n())
## # A tibble: 20 x 3
## niveled_psh n cat
## <fct> <int> <int>
## 1 Primario 7131 1
## 2 Primaria/EGB completo 3350 2
## 3 Secundario/Polimodal completo 2611 3
## 4 sin_información 2467 4
## 5 Secundario/Polimodal incompleto 2206 5
## 6 Secundario 1962 6
## 7 Primaria/EGB incompleto 1652 7
## 8 <NA> 1368 8
## 9 Ninguno 1033 9
## 10 Universitario completo 794 10
## 11 Terciario completo 790 11
## 12 Universitario incompleto 513 12
## 13 Universitario 472 13
## 14 Terciario 437 14
## 15 Terciario incompleto 321 15
## 16 Sin instrucción (incluye nunca asistió o sólo asistió a sala de … 311 16
## 17 EGB 110 17
## 18 Polimodal 36 18
## 19 Posgrado Universitario 32 19
## 20 Educación especial 14 20
Aquí se presentan varios problemas:
- Hay demasiadas (20) categorías y algunas se superponen. Las variables
v241a
yv244a
no tienen las mismas categorías quenivel_ed
. Será necesario compactarlas. - Los
NA
son los casos inimputables, será necesario indicarlo como tal.
Esquemas de recodificación
reco$niveled_psh <- list(ninguno = c("Sin instrucción (incluye nunca asistió o sólo asistió a sala de 5)", "Primaria/EGB incompleto", "Ninguno"),
primaria = c( "Primario","Primaria/EGB completo", "Secundario/Polimodal incompleto", "EGB"),
secundaria = c("Secundario/Polimodal completo", "Terciario incompleto", "Secundario", "Polimodal"),
terciario = c( "Terciario", "Terciario completo", "Universitario incompleto"),
universitario = c("Universitario completo", "Universitario", "Posgrado Universitario"),
otro = c("Educación especial"))
reco$niveled_psh %>%
map_df(~`length<-`(.x, 3)) %>%
gather("Código nuevo", "Códigos originales") %>%
drop_na() %>%
knitr::kable(caption = "Recodificación de la variable Nivel Educativo del PSH")
Código nuevo | Códigos originales |
---|---|
ninguno | Sin instrucción (incluye nunca asistió o sólo asistió a sala de 5) |
ninguno | Primaria/EGB incompleto |
ninguno | Ninguno |
primaria | Primario |
primaria | Primaria/EGB completo |
primaria | Secundario/Polimodal incompleto |
secundaria | Secundario/Polimodal completo |
secundaria | Terciario incompleto |
secundaria | Secundario |
terciario | Terciario |
terciario | Terciario completo |
terciario | Universitario incompleto |
universitario | Universitario completo |
universitario | Universitario |
universitario | Posgrado Universitario |
otro | Educación especial |
reco$nivel_ed <- list(ninguno = c("Sin instrucción (incluye nunca asistió o sólo asistió a sala de 5)", "Primaria/EGB incompleto"),
primaria = c("Primaria/EGB completo", "Secundario/Polimodal incompleto"),
secundaria = c("Secundario/Polimodal completo", "Terciario incompleto"),
terciario = c("Terciario completo", "Universitario incompleto"),
universitario = "Universitario completo",
otro = c("Educación especial", "NS/NR"))
reco$nivel_ed %>%
map_df(~`length<-`(.x, 2)) %>%
gather("Código nuevo", "Códigos originales") %>%
drop_na() %>%
knitr::kable(caption = "Recodificación de la variable Nivel Educativo de la persona")
Código nuevo | Códigos originales |
---|---|
ninguno | Sin instrucción (incluye nunca asistió o sólo asistió a sala de 5) |
ninguno | Primaria/EGB incompleto |
primaria | Primaria/EGB completo |
primaria | Secundario/Polimodal incompleto |
secundaria | Secundario/Polimodal completo |
secundaria | Terciario incompleto |
terciario | Terciario completo |
terciario | Universitario incompleto |
universitario | Universitario completo |
otro | Educación especial |
otro | NS/NR |
Movilidad educativa
Tabla de movilidad (toma 1)
left_join(personas, niveled_psh) %>%
filter(v108 > 29) %>%
select(niveled_psh, nivel_ed, f_calib3, v108) %>%
mutate(niveled_psh = as.factor(niveled_psh),
nivel_ed = as_factor(nivel_ed),
niveled_psh = fct_collapse(niveled_psh, !!!reco$niveled_psh ),
niveled_psh = fct_relevel(niveled_psh, !!!names(reco$niveled_psh)),
niveled_psh = fct_explicit_na(niveled_psh, "inimputable"),
nivel_ed = fct_collapse(nivel_ed, !!!reco$nivel_ed),
v108 = cut_interval(v108, 3)) %>%
count(niveled_psh, nivel_ed, wt = f_calib3) -> nivel_ed_x_nivelel_psh
nivel_ed_x_nivelel_psh %>%
spread(nivel_ed, n, 0) %>%
knitr::kable(caption = "Frecuencia condicional de nivel educativo de la persona y su PSH.^[Aplica ponderador muestral]")
niveled_psh | ninguno | primaria | secundaria | terciario | universitario | otro |
---|---|---|---|---|---|---|
ninguno | 426524 | 655866 | 267077 | 71365 | 18754 | 3331 |
primaria | 1035109 | 4096268 | 2686820 | 1283041 | 628661 | 18776 |
secundaria | 64911 | 413252 | 849743 | 620516 | 435707 | 9720 |
terciario | 24426 | 40481 | 176891 | 217953 | 219170 | 1204 |
universitario | 6634 | 23808 | 102448 | 207315 | 339806 | 358 |
otro | 427 | 3206 | 0 | 1196 | 0 | 790 |
sin_información | 570353 | 1183791 | 625197 | 219731 | 120576 | 1444 |
inimputable | 322879 | 416540 | 198197 | 82626 | 33142 | 3210 |
Tabla de movilidad (proporción de Nivel educativo del PSH)
Las columnas indican el nivel eductativo del PSH, las filas el nivel educativo de la persona.
Ejp: un 6.4% de las persona mayores de 30 años que lograron educación primaria vivieron/viven en un hogar cuyo PSH alcanzó educación universitaria.
nivel_ed_x_nivelel_psh %>%
group_by(niveled_psh) %>%
mutate(prop = n / sum(n),
prop = scales::percent(prop)) %>%
select(-n) %>%
spread(niveled_psh, prop, 0) %>%
knitr::kable(caption = "Nivel educativo de orígen y destino. Proporción de nivel según el orígen ^[Aplica ponderador muestral]")
nivel_ed | ninguno | primaria | secundaria | terciario | universitario | otro | sin_información | inimputable |
---|---|---|---|---|---|---|---|---|
ninguno | 29.6% | 10.6% | 2.71% | 3.59% | 0.98% | 7.6% | 21.0% | 30.6% |
primaria | 45.5% | 42.0% | 17.26% | 5.95% | 3.50% | 57.1% | 43.5% | 39.4% |
secundaria | 18.5% | 27.6% | 35.50% | 26.01% | 15.06% | 0 | 23.0% | 18.8% |
terciario | 4.9% | 13.2% | 25.92% | 32.05% | 30.47% | 21.3% | 8.1% | 7.8% |
universitario | 1.3% | 6.4% | 18.20% | 32.22% | 49.94% | 0 | 4.4% | 3.1% |
otro | 0.2% | 0.2% | 0.41% | 0.18% | 0.05% | 14.1% | 0.1% | 0.3% |
nivel_ed_x_nivelel_psh %>%
group_by(nivel_ed) %>%
mutate(prop = n / sum(n),
prop = scales::percent(prop)) %>%
select(-n) %>%
spread(niveled_psh, prop, 0) %>%
knitr::kable(caption = "Proporción de orígen según destino^[Aplica ponderador muestral]")
nivel_ed | ninguno | primaria | secundaria | terciario | universitario | otro | sin_información | inimputable |
---|---|---|---|---|---|---|---|---|
ninguno | 17.40% | 42.23% | 2.65% | 1.00% | 0.27% | 0.02% | 23.27% | 13.17% |
primaria | 9.598% | 59.946% | 6.048% | 0.592% | 0.348% | 0.047% | 17.324% | 6.096% |
secundaria | 5.44% | 54.76% | 17.32% | 3.61% | 2.09% | 0 | 12.74% | 4.04% |
terciario | 2.639% | 47.454% | 22.950% | 8.061% | 7.668% | 0.044% | 8.127% | 3.056% |
universitario | 1.04% | 35.01% | 24.26% | 12.20% | 18.92% | 0 | 6.71% | 1.85% |
otro | 8.58% | 48.35% | 25.03% | 3.10% | 0.92% | 2.03% | 3.72% | 8.27% |
library(ggalluvial)
nivel_ed_x_nivelel_psh %>%
ggplot(aes(y = n, axis1 = niveled_psh, axis2 = nivel_ed)) +
geom_alluvium(aes(fill = niveled_psh), width = 1/12) +
geom_stratum(width = 1/12, color = "grey") +
geom_label(stat = "stratum", infer.label = TRUE) +
scale_y_continuous(sec.axis = dup_axis(name = "Nivel educativo de la persona")) +
theme_minimal() +
theme(legend.position = "none",
axis.text = element_blank()) +
labs(x = NULL,
y = "Nivel educativo del PSH",
title = "Movilidad educativa intergeneracional")
library(ggforce)
left_join(personas, niveled_psh) %>%
select(niveled_psh, nivel_ed, v108) %>%
filter(v108 > 29) %>%
mutate(niveled_psh = as.factor(niveled_psh),
nivel_ed = as_factor(nivel_ed),
niveled_psh = fct_collapse(niveled_psh, !!!reco$niveled_psh ),
niveled_psh = fct_relevel(niveled_psh, !!!names(reco$niveled_psh)),
niveled_psh = fct_explicit_na(niveled_psh, "inimputable"),
nivel_ed = fct_collapse(nivel_ed, !!!reco$nivel_ed),
# Grupos de edad
edad = cut(v108,
breaks = c(-Inf, 40, 50, 65, Inf),
labels = c("30-40 años", "41-50 años", "51-65", "65 o más" ))) %>%
rename("Nivel educativo\ndel PSH" = niveled_psh,
"Nivel educativo\nde la persona" = nivel_ed) %>%
# Filtrar eliminando las categorías con poca información
filter_all(all_vars(!. %in% c("otro", "sin_información", "inimputable"))) %>%
#Preparar los datos para el gráfico
gather_set_data(c(1:2)) %>%
# Reordenar el factor para que los ejes en el gráfico tengan este órden el eje x
mutate(x = factor(x, levels = c("Nivel educativo\ndel PSH", "Nivel educativo\nde la persona"))) %>%
ggplot(aes(x, id = id, split = y, value = 1)) +
geom_parallel_sets(aes(fill = `Nivel educativo\nde la persona`), show.legend = FALSE, alpha = 0.3) +
geom_parallel_sets_axes(axis.width = 0.1, color = "lightgrey", fill = "white") +
geom_parallel_sets_labels(angle = 0) +
scale_x_discrete(expand = c(0.08, 0.08)) +
facet_wrap(~edad, scales = "free") +
theme_minimal() +
theme(axis.text.y = element_blank()) +
labs(title = "Movilidad educativa intergeneracional en Argentina",
subtitle = "Por grupos de edad a 2015",
caption = "n = 13912. Mayores de 30 años con información completa sobre nivel educativo propio y del PSH
Elaboración propia con datos de la ENES-PISAC",
x = NULL)