Trabajo Seminario Doctorado

Anexo de análisis de datos con R

Autor/a

Javiera Rojas Cifuentes

Fecha de publicación

15 de abril de 2025

1 Presentación

El presente documento busca funcionar como respaldo para el trabajo del seminario Herramientas metodológicas cuantitativas para el estudio de la desigualdad, la estructura social y la pobreza dictado por la docente Jésica Pla y el docente Santiago Poy durante 2024. A continuación se detalla el procesamiento de la fuente de datos consignada en el informe, dejando a la vista un código reproducible como respaldo del trabajo de análisis de datos.

2 Procesamiento inicial de los datos

2.1 Entorno de trabajo

Se utiliza un proyecto de R (.Rproj) con las siguientes carpetas:

  • codigo

  • datos

  • resultados

Se prepara el entorno de trabajo instalando los paquetes necesarios para preparación y análisis de datos.

# Instalación de paquete pacman
# Función p_load permite evaluar si instalar y/o cargar paquetes
# install.packages("pacman")   # ejecutar sólo si no está instalado
pacman::p_load(tidyverse,      # funciones generales
               haven,          # manipulación archivos spss  
               srvyr,          # para implementar ponderadores
               gtsummary,      # herramientas para diseñar tablas de resultados
               kableExtra,     # para formato de tablas
               modelsummary,   # diseño tablas de regresión
               summarytools)   # herramientas para estadísticos de resumen
options(OutDec = ",")          # Separador decimal

2.2 Lectura de base de datos original

La base de datos de CASEN 2022 -y toda la documentación asociada- se encuentra para descarga en el repositorio oficial de la encuesta. La descarga se realizó de manera manual y se descomprimió en la carpeta datos ya indicada. Luego, para facilitar su procesamiento se cargó en R y se guardo en formato .rds. Se indica el código de este último paso a continuación.

casen <- haven::read_sav("datos/Base de datos Casen 2022 SPSS_18 marzo 2024.sav")
saveRDS(casen, file = "datos/casen22.rds")
remove(casen) # eliminar del entorno base de origen SAV

Posteriormente leemos la base de datos de CASEN 2022 en formato .rds.

casen22 <- readRDS("datos/casen22.rds")

2.3 Preparación de variables para análisis

A continuación se seleccionan las variables consideradas para el análisis.

# Seleccionar variables de interés desde bbdd completa
casen_vars <- casen22 %>% 
  select(expr, varstrat, varunit,    # diseño muestral complejo
         folio, pco1,                # identificación hogar y jefatura
         pobreza,                    # pobreza
         sexo, edad, area)           # variables de segmentación

# Eliminar base completa para maximizar ram
remove(casen22)

Luego se preparan para el análisis. Se eliminan los atributos del objeto que vienen desde el formato SPSS; se editan y colapsan etiquetas cuando es necesario; se filtran los casos de interés para el análisis.

# configurar variables (eliminar configuraciones específicas de SPSS)
casen_vars <- casen_vars %>%
  mutate_at(vars(1:5,8), ~as.numeric(.)) %>% # diseño muestral y edad como numeric
  mutate_if(
    is.labelled,
    funs(as_factor(.))) %>% 
  mutate(across(everything(), ~ {
    attr(.x, "label") <- NULL
    .x
  }))

# Colapsar codificación de pobreza
casen_vars$pobreza <- fct_collapse(casen_vars$pobreza,
  Pobre = c("Pobreza extrema", "Pobreza no extrema"),
  `No pobre` = "No pobreza")

# Editar etiquetas de respuesta de sexo
levels(casen_vars$sexo) <- sub("^\\d+\\.\\s*", "", levels(casen_vars$sexo))

# Crear edad en tramos
casen_vars <- casen_vars |>
  mutate(
    edad_tramo = case_when(
      edad < 18 ~ "NNA",
      edad >= 18 & edad <= 29 ~ "Joven",
      edad >= 30 & edad <= 60 ~ "Adulto",
      edad > 60 ~ "Tercera edad"),
    edad_tramo = factor(
      edad_tramo,
      levels = c("NNA", "Joven", "Adulto", "Tercera edad")
    )
  )

# Identificador de personas en hogares de jefatura femenina
casen_vars <- casen_vars |>
  group_by(folio) |>
  mutate(
    jefatura = if (any(pco1 == 1 & sexo == "Mujer")) {
      "Femenina"
    } else {
      "Masculina"
    }
  ) |>
  ungroup()

# Variable jefatura: definir como factor
casen_vars$jefatura <- as.factor(casen_vars$jefatura)

# Seleccionar casos completos en variable de analisis
casen_vars <- casen_vars |>
  filter(!is.na(pobreza))

3 Resultados bivariados

3.1 Tabla de asociación entre variables

# Lista de variables categóricas
data <- select(casen_vars, pobreza, sexo, jefatura, area, edad_tramo)
vars <- c("pobreza", "sexo", "jefatura", "area", "edad_tramo")

# Obtener todas las combinaciones posibles de 2 variables
pares <- combn(vars, 2, simplify = FALSE)

# Función para calcular chi-cuadrado y extraer estadísticas clave
chi_results <- map_dfr(pares, function(pair) {
  tab <- table(data[[pair[1]]], data[[pair[2]]])
  test <- suppressWarnings(chisq.test(tab))  # evita warnings si hay valores esperados bajos
  
  tibble(
    var1 = pair[1],
    var2 = pair[2],
    chi_squared = round(test$statistic, 3),
    df = test$parameter,
    p_value = signif(test$p.value, 3)
  )
})

# Desactivar notación científica
chi_results$p_value <- round(as.numeric(gsub(",", ".", format(chi_results$p_value, scientific = FALSE))
), 2)

# Agregar columna evaluación lógica
chi_results <- chi_results %>%  mutate(significativo = case_when(
  p_value < 0.05 ~ "Sí",
  p_value > 0.05 ~ "No"
))

# Ver resultado
kable(chi_results[1:4,], col.names = c("Var1", "Var2", "Chi-squared", "DF", "p_redondeado", "p<0,05"))
Var1 Var2 Chi-squared DF p_redondeado p<0,05
pobreza sexo 37,118 1 0
pobreza jefatura 677,701 1 0
pobreza area 610,214 1 0
pobreza edad_tramo 2759,867 3 0

3.2 Visualización descriptiva

3.2.1 Incidencia de pobreza según sexo

ctable(casen_vars$sexo, casen_vars$pobreza, weights = casen_vars$expr,
       headings = FALSE) %>% print(method = "render")
sexo
sexo Pobre No pobre Total
Hombre 596221,0 ( 6,1% ) 9210061,0 ( 93,9% ) 9806282,0 ( 100,0% )
Mujer 695603,0 ( 6,9% ) 9362773,0 ( 93,1% ) 10058376,0 ( 100,0% )
Total 1291824,0 ( 6,5% ) 18572834,0 ( 93,5% ) 19864658,0 ( 100,0% )

Generated by summarytools 1.1.3 (R version 4.4.3)
2025-04-15

casen_vars %>% as_survey(weights = expr) %>% 
  group_by(sexo, pobreza) %>% 
  summarize(n = survey_total()) %>% 
  select(-n_se) %>% 
  mutate(freq = n / sum(n)) %>% 
  ## GRÁFICO
  ggplot(aes(x= sexo, y = freq, fill = pobreza ,label = scales::percent(freq))) +
  geom_bar(stat = 'identity') +
  geom_text(position = position_stack(vjust = .5, reverse = F), colour = "white", size = 3) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  scale_fill_discrete("Situación de pobreza")+
  labs(x = 'Sexo', y = '%', 
       caption = "Elaboración propia con base en CASEN 2022") +
  theme_linedraw()

3.2.2 Incidencia de pobreza según área

ctable(casen_vars$area, casen_vars$pobreza, weights = casen_vars$expr,
       headings = FALSE) %>% print(method = "render")
area
area Pobre No pobre Total
Urbano 1067809,0 ( 6,1% ) 16543793,0 ( 93,9% ) 17611602,0 ( 100,0% )
Rural 224015,0 ( 9,9% ) 2029041,0 ( 90,1% ) 2253056,0 ( 100,0% )
Total 1291824,0 ( 6,5% ) 18572834,0 ( 93,5% ) 19864658,0 ( 100,0% )

Generated by summarytools 1.1.3 (R version 4.4.3)
2025-04-15

casen_vars %>% as_survey(weights = expr) %>% 
  group_by(area, pobreza) %>% 
  summarize(n = survey_total()) %>% 
  select(-n_se) %>% 
  mutate(freq = n / sum(n)) %>% 
  ## GRÁFICO
  ggplot(aes(x= area, y = freq, fill = pobreza ,label = scales::percent(freq))) +
  geom_bar(stat = 'identity') +
  geom_text(position = position_stack(vjust = .5, reverse = F), colour = "white", size = 3) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  scale_fill_discrete("Situación de pobreza")+
  labs(x = 'Área de residencia', y = '%', 
       caption = "Elaboración propia con base en CASEN 2022") +
  theme_linedraw()

3.2.3 Incidencia de pobreza según tramo de edad

ctable(casen_vars$edad_tramo, casen_vars$pobreza, weights = casen_vars$expr,
       headings = FALSE) %>% print(method = "render")
edad_tramo
edad_tramo Pobre No pobre Total
NNA 467914,0 ( 10,5% ) 3983135,0 ( 89,5% ) 4451049,0 ( 100,0% )
Joven 233156,0 ( 6,8% ) 3219797,0 ( 93,2% ) 3452953,0 ( 100,0% )
Adulto 490630,0 ( 5,7% ) 8071178,0 ( 94,3% ) 8561808,0 ( 100,0% )
Tercera edad 100124,0 ( 2,9% ) 3298724,0 ( 97,1% ) 3398848,0 ( 100,0% )
Total 1291824,0 ( 6,5% ) 18572834,0 ( 93,5% ) 19864658,0 ( 100,0% )

Generated by summarytools 1.1.3 (R version 4.4.3)
2025-04-15

casen_vars %>% as_survey(weights = expr) %>% 
  group_by(edad_tramo, pobreza) %>% 
  summarize(n = survey_total()) %>% 
  select(-n_se) %>% 
  mutate(freq = n / sum(n)) %>% 
  ## GRÁFICO
  ggplot(aes(x= edad_tramo, y = freq, fill = pobreza ,label = scales::percent(freq))) +
  geom_bar(stat = 'identity') +
  geom_text(position = position_stack(vjust = .5, reverse = F), colour = "white", size = 3) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  scale_fill_discrete("Situación de pobreza")+
  labs(x = 'Tramo de edad', y = '%', 
       caption = "Elaboración propia con base en CASEN 2022") +
  theme_linedraw()

3.2.4 Incidencia de pobreza según tipo de jefatura del hogar

ctable(casen_vars$jefatura, casen_vars$pobreza, weights = casen_vars$expr,
       headings = FALSE) %>% print(method = "render")
jefatura
jefatura Pobre No pobre Total
Femenina 770535,0 ( 7,9% ) 8955141,0 ( 92,1% ) 9725676,0 ( 100,0% )
Masculina 521289,0 ( 5,1% ) 9617693,0 ( 94,9% ) 10138982,0 ( 100,0% )
Total 1291824,0 ( 6,5% ) 18572834,0 ( 93,5% ) 19864658,0 ( 100,0% )

Generated by summarytools 1.1.3 (R version 4.4.3)
2025-04-15

casen_vars %>% as_survey(weights = expr) %>% 
  group_by(jefatura, pobreza) %>% 
  summarize(n = survey_total()) %>% 
  select(-n_se) %>% 
  mutate(freq = n / sum(n)) %>% 
  ## GRÁFICO
  ggplot(aes(x= jefatura, y = freq, fill = pobreza ,label = scales::percent(freq))) +
  geom_bar(stat = 'identity') +
  geom_text(position = position_stack(vjust = .5, reverse = F), colour = "white", size = 3) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  scale_fill_discrete("Situación de pobreza")+
  labs(x = 'Jefatura del hogar', y = '%', 
       caption = "Elaboración propia con base en CASEN 2022") +
  theme_linedraw()

4 Resultado multivariable

4.1 Regresión logística múltiple

Para modelar los datos primero se definieron todas las variables como factor en el apartado de procesamiento de la información. Se definen las categorías de referencia para el análisis y en el caso de edad se simplifican las categorías de respuesta, agrupando a niñas, niños, adolescentes y jóvenes (sub 30 años) en una misma categoría, y al resto (adultos y tercera edad, de 30 años hacia arriba) en otra categoría.

# Niveles de variable pobreza: categoría referencia = "Pobre"
casen_vars$pobreza <- relevel(casen_vars$pobreza, 
                        ref = "No pobre") 

# Variable jefatura: categoría referencia = "Masculina"

casen_vars$jefatura <- relevel(casen_vars$jefatura, 
                        ref = "Masculina") 

# Variable edad: agrupar categorías y definir referencia = "NNA-joven"  
casen_vars$edad_tramo2 <- fct_collapse(casen_vars$edad_tramo,
  "NNA - Joven" = c("NNA", "Joven"),
  "Adulto - 3a edad" = c("Adulto", "Tercera edad"))

casen_vars$edad_tramo2 <- relevel(casen_vars$edad_tramo2, 
                        ref = "Adulto - 3a edad") 

# Variable área: definir categoría referencia = "Urbano"
casen_vars$area <- relevel(casen_vars$area, 
                        ref = "Urbano")

Con tal procesamiento de datos definimos el modelo de regresión logística y construimos resultados con formato para interpretación.

# Modelamiento
rlogit <-  glm(pobreza ~ edad_tramo2 + jefatura + area,  # variables modeladas
                data = casen_vars,                # base de datos
                family = "binomial")

# Tabla resumen del modelo
summary(rlogit)

Call:
glm(formula = pobreza ~ edad_tramo2 + jefatura + area, family = "binomial", 
    data = casen_vars)

Coefficients:
                       Estimate Std. Error z value Pr(>|z|)    
(Intercept)            -3,18745    0,01720 -185,34   <2e-16 ***
edad_tramo2NNA - Joven  0,66557    0,01706   39,02   <2e-16 ***
jefaturaFemenina        0,44466    0,01749   25,43   <2e-16 ***
areaRural               0,56530    0,01928   29,32   <2e-16 ***
---
Signif. codes:  0 '***' 0,001 '**' 0,01 '*' 0,05 '.' 0,1 ' ' 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 108254  on 202110  degrees of freedom
Residual deviance: 105348  on 202107  degrees of freedom
AIC: 105356

Number of Fisher Scoring iterations: 5
# Diseño resultados para informe
tabla_rlogit <- modelsummary(
  list("Log-odds" = rlogit, "Odds Ratio" = rlogit),
  exponentiate = c(FALSE, TRUE),
  statistic = "conf.int",
  output = "markdown"
)
tabla_rlogit

Modelo de regresión logística

Log-odds Odds Ratio
(Intercept) -3,187 0,041
[-3,221, -3,154] [0,040, 0,043]
edad_tramo2NNA - Joven 0,666 1,946
[0,632, 0,699] [1,882, 2,012]
jefaturaFemenina 0,445 1,560
[0,410, 0,479] [1,507, 1,614]
areaRural 0,565 1,760
[0,527, 0,603] [1,695, 1,828]
Num.Obs. 202111 202111
AIC 105356,0 105356,0
BIC 105396,9 105396,9
Log.Lik. -52674,022 -52674,022
RMSE 0,26 0,26