El análisis del uso del tiempo permite comprender cómo se distribuyen las actividades diarias de la población y evidenciar desigualdades sociales y de género, en este caso particular, en relación con el trabajo no remunerado. Este tipo de trabajo, que incluye tareas domésticas y de cuidado, suele recaer de manera de desigual entre hombres y mujeres. Por ejemplo, según el Equipo Latinoamericano de Justicia Y Genero (ELA), sostiene que en la mayoría de los hogares las responsabilidades y tareas domésticas, de crianza y de cuidado recaen sobre las mujeres. En Argentina, las mujeres participan en las actividades domésticas no remuneradas en promedio un 89.9%, 20 puntos más que los varones.
En este trabajo se utiliza la Encuesta de Usos del Tiempo de la Ciudad de Buenos Aires (2016) con el objetivo de aplicar técnicas de Machine Learning para modelar y predecir la cantidad de horas diarias dedicadas al trabajo no remunerado a partir de variables sociodemográficas. Se implementa un modelo Random Forest para regresión.
El objetivo principal de este trabajo es predecir la cantidad de horas diarias dedicadas al trabajo no remunerado, analizando el rol del sexo, la edad, la condición laboral y el tipo de día, entre otras variables.
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.5.1
## Warning: package 'ggplot2' was built under R version 4.5.1
## Warning: package 'purrr' was built under R version 4.5.1
## Warning: package 'dplyr' was built under R version 4.5.1
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 4.0.0 ✔ tibble 3.2.1
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ✔ purrr 1.1.0
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(tidymodels)
## Warning: package 'tidymodels' was built under R version 4.5.2
## ── Attaching packages ────────────────────────────────────── tidymodels 1.4.1 ──
## ✔ broom 1.0.12 ✔ rsample 1.3.2
## ✔ dials 1.4.2 ✔ tailor 0.1.0
## ✔ infer 1.1.0 ✔ tune 2.0.1
## ✔ modeldata 1.5.1 ✔ workflows 1.3.0
## ✔ parsnip 1.4.1 ✔ workflowsets 1.1.1
## ✔ recipes 1.3.1 ✔ yardstick 1.3.2
## Warning: package 'broom' was built under R version 4.5.2
## Warning: package 'dials' was built under R version 4.5.2
## Warning: package 'scales' was built under R version 4.5.1
## Warning: package 'infer' was built under R version 4.5.2
## Warning: package 'modeldata' was built under R version 4.5.2
## Warning: package 'parsnip' was built under R version 4.5.2
## Warning: package 'recipes' was built under R version 4.5.2
## Warning: package 'rsample' was built under R version 4.5.2
## Warning: package 'tailor' was built under R version 4.5.2
## Warning: package 'tune' was built under R version 4.5.2
## Warning: package 'workflows' was built under R version 4.5.2
## Warning: package 'workflowsets' was built under R version 4.5.2
## Warning: package 'yardstick' was built under R version 4.5.2
## ── Conflicts ───────────────────────────────────────── tidymodels_conflicts() ──
## ✖ scales::discard() masks purrr::discard()
## ✖ dplyr::filter() masks stats::filter()
## ✖ recipes::fixed() masks stringr::fixed()
## ✖ dplyr::lag() masks stats::lag()
## ✖ yardstick::spec() masks readr::spec()
## ✖ recipes::step() masks stats::step()
library(stringi)
## Warning: package 'stringi' was built under R version 4.5.2
library(ranger)
## Warning: package 'ranger' was built under R version 4.5.2
# Cargar datos de la Encuesta de Usos del Tiempo (CABA 2016)
data <- read.csv("encuesta_uso_tiempo_2016.csv")
# Ver estructura general
glimpse(data)
## Rows: 2,336
## Columns: 27
## $ hogar <chr> "1_1", "2_1", "3_1", "4_1", "5_1", "6_1", "…
## $ sexo <chr> "Varon", "Varon", "Varon", "Varon", "Varon"…
## $ edad <int> 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,…
## $ dia_laborable <chr> "D\xeda no laborable", "D\xeda no laborable…
## $ trabajo_pago <dbl> 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0…
## $ trabajo_domestico_no_pago <dbl> 0.1, 1.0, 0.2, 1.8, 0.0, 3.0, 0.3, 0.3, 0.3…
## $ voluntariados <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ estudio_educacion <dbl> 0.0, 8.3, 11.3, 4.0, 8.3, 0.0, 6.7, 8.8, 10…
## $ recreacion <dbl> 9.0, 2.7, 2.6, 7.7, 4.7, 4.2, 2.2, 4.9, 1.8…
## $ aplicaciones <dbl> 7.3, 2.5, 0.3, 3.0, 1.8, 4.8, 4.7, 1.5, 2.5…
## $ tareas_cuidados <dbl> 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2, 0.0, 0.0…
## $ cuidado_personal <dbl> 8.2, 10.2, 10.6, 9.5, 9.3, 15.7, 11.8, 9.8,…
## $ trabajo_pago2 <dbl> 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0…
## $ trabajo_domestico_no_pago2 <dbl> 0.1, 1.0, 0.2, 1.3, 0.0, 3.0, 0.2, 0.3, 0.1…
## $ voluntariados2 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ estudio_educacion2 <dbl> 0.0, 8.3, 11.3, 4.0, 8.3, 0.0, 6.6, 8.8, 10…
## $ recreacion2 <dbl> 8.8, 2.3, 2.1, 7.2, 4.7, 2.3, 1.7, 4.3, 0.9…
## $ aplicaciones2 <dbl> 7.3, 2.5, 0.3, 3.0, 1.8, 4.8, 4.7, 1.5, 2.5…
## $ tareas_cuidados2 <dbl> 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0…
## $ cuidado_personal2 <dbl> 7.9, 9.8, 10.1, 8.5, 9.3, 13.8, 10.9, 9.1, …
## $ dia_tipico <chr> "D\xeda at\xedpico", "D\xeda at\xedpico", "…
## $ rango_etario <chr> "14-24", "14-24", "14-24", "14-24", "14-24"…
## $ nivel_educativo <chr> "Secundario incompleto", "Secundario incomp…
## $ relacion_parentesco_jefe <chr> "Hijo/a - Hijastro/a", "Hijo/a - Hijastro/a…
## $ tipo_hogar <chr> "Nuclear con nucleo incompleto", "Nuclear c…
## $ quintil_ingreso <chr> "5to quintil", "5to quintil", "5to quintil"…
## $ estado_ocupacional <chr> "Inactivo", "Inactivo", "Inactivo", "Inacti…
sexo edad nivel_educativo rango_etario tipo_hogar estado_ocupacional dia_laborable
data_ml <- data %>%
select(
horas_no_rem = trabajo_domestico_no_pago,
sexo,
edad,
nivel_educativo,
rango_etario,
tipo_hogar,
estado_ocupacional,
dia_laborable
) %>%
drop_na()
data_ml <- data_ml %>%
mutate(across(where(is.character),
~ stri_trans_general(., "Latin-ASCII")))
set.seed(123)
split <- initial_split(data_ml, prop = 0.8)
train_data <- training(split)
test_data <- testing(split)
rf_recipe <- recipe(horas_no_rem ~ ., data = train_data) %>%
step_dummy(all_nominal_predictors()) %>%
step_normalize(all_numeric_predictors())
rf_model <- rand_forest(
trees = 500,
mode = "regression"
) %>%
set_engine("ranger", importance = "permutation")
rf_wf <- workflow() %>%
add_recipe(rf_recipe) %>%
add_model(rf_model)
rf_fit <- rf_wf %>%
fit(data = train_data)
rf_fit
## ══ Workflow [trained] ══════════════════════════════════════════════════════════
## Preprocessor: Recipe
## Model: rand_forest()
##
## ── Preprocessor ────────────────────────────────────────────────────────────────
## 2 Recipe Steps
##
## • step_dummy()
## • step_normalize()
##
## ── Model ───────────────────────────────────────────────────────────────────────
## Ranger result
##
## Call:
## ranger::ranger(x = maybe_data_frame(x), y = y, num.trees = ~500, importance = ~"permutation", num.threads = 1, verbose = FALSE, seed = sample.int(10^5, 1))
##
## Type: Regression
## Number of trees: 500
## Sample size: 1868
## Number of independent variables: 15
## Mtry: 3
## Target node size: 5
## Variable importance mode: permutation
## Splitrule: variance
## OOB prediction error (MSE): 4.67181
## R squared (OOB): 0.2415566
results_test <- test_data %>%
bind_cols(predict(rf_fit, test_data))
metrics(
results_test,
truth = horas_no_rem,
estimate = .pred
)
## # A tibble: 3 × 3
## .metric .estimator .estimate
## <chr> <chr> <dbl>
## 1 rmse standard 2.10
## 2 rsq standard 0.272
## 3 mae standard 1.54
En el conjunto de test, el modelo obtuvo los siguientes resultados: - rmse: 2,11 horas - rsq: 0,27 - mae: 1,54 horas
Estos valores indican que en promedio el error absoluto del modelo es de aproximadamente una hora y media en la predicción del tiempo dedicado al trabajo no remunerado.
ggplot(results_test, aes(x = horas_no_rem, y = .pred)) +
geom_point(alpha = 0.6) +
geom_abline(slope = 1, intercept = 0, linetype = "dashed", color = "red") +
labs(
title = "Valores reales vs predichos",
x = "Horas reales de trabajo no remunerado",
y = "Horas predichas"
) +
theme_minimal()
El grafico muestra que el modelo captura la tendencia general del trabajo no remunerado, concentrando la mayoría de las observaciones cerca de la línea de igualdad. Sin embargo se observa una dispersión creciente a medida que aumentan las horas reales. Esto indicaría que el modelo presenta mayores dificultades para predecir valores extremos.
library(vip)
## Warning: package 'vip' was built under R version 4.5.2
##
## Adjuntando el paquete: 'vip'
## The following object is masked from 'package:utils':
##
## vi
vip(pull_workflow_fit(rf_fit)$fit)
## Warning: `pull_workflow_fit()` was deprecated in workflows 0.2.3.
## ℹ Please use `extract_fit_parsnip()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
El grafico muestra que:
El modelo Random Forest permitió aproximar de manera razonable la cantidad de horas dedicadas al trabajo no remunerado. Si bien el poder explicativo del modelo es moderado, los resultados son coherentes.
La importancia de variables como sexo, edad y el estado ocupacional refuerza la evidencia de que el trabajo no remunerado está fuertemente condicionado por factores estructurales y de género.
Un posible análisis futuro podría profundizar en las tareas de cuidado de manera especifica, dado que el presente analisis considera únicamente las horas totales de trabajo nno remunerado sin distienguir entre distintos tipos de actividades.