Se plantea como pregunta de investigaciĂłn: ÂżQuĂ© variaciones existen en la percepciĂłn de reconocimiento laboral entre mujeres y varones segĂșn nivel educativo, regiĂłn, rango etario, sector de ocupaciĂłn y rama de actividad? Esta pregunta se abordarĂĄ analizando la encuesta ECETSS 2018, comparando la percepciĂłn de reconocimiento general por cada sexo, para luego analizar variaciones al incorporar una tercera variable como nivel educativo, regiĂłn, rango etario, sector de ocupaciĂłn y rama de actividad.
# Se declara la lista de paquetes requeridos: lectura de SPSS, manipulaciĂłn,
# completado de combinaciones y elaboraciĂłn/guardado de grĂĄficos.
# Instalar paquetes solo si aĂșn no estĂĄn instalados
paquetes <- c("haven", "dplyr", "tidyr", "ggplot2", "forcats", "scales","ggforce")
# Se compara la lista requerida con los paquetes ya disponibles en R y se
# conserva Ășnicamente aquello que falta, evitando instalaciones repetidas.
paquetes_faltantes <- paquetes[!paquetes %in% installed.packages()[, "Package"]]
if (length(paquetes_faltantes) > 0) {
install.packages(paquetes_faltantes)
}
# Cargar los paquetes para que sus funciones estén disponibles durante el anålisis.
library(haven)
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(tidyr)
library(ggplot2)
library(forcats)
library(scales)
library(ggforce)
# ------------------------------------------------------------
# 1. Leer la base
# ------------------------------------------------------------
# Importa el archivo SPSS. Las etiquetas de valores se preservan como atributos
# y luego se convertirĂĄn a texto legible con as_factor().
datos <- read_sav("ECETSS_ocupados.sav")
# Verificar que las variables requeridas existan antes de transformar la base;
# asĂ el anĂĄlisis se detiene con un mensaje claro si se cambiĂł el archivo fuente.
variables_necesarias <- c(
"recomp_valorac",
"C3P16.1",
"nivel_ed",
"region",
"C0P10.3",
"sector",
"ramacaes_o"
)
# setdiff identifica las variables solicitadas que no figuran entre las columnas importadas.
variables_faltantes <- setdiff(variables_necesarias, names(datos))
if (length(variables_faltantes) > 0) {
stop(
paste(
"No se encontraron estas variables en la base:",
paste(variables_faltantes, collapse = ", ")
)
)
}
# ------------------------------------------------------------
# 2. Preparar la base y traducir las variables
# ------------------------------------------------------------
# Construye una base analĂtica con solo las variables necesarias. transmute()
# crea/renombra columnas y descarta el resto de la base original.
base_reconocimiento <- datos %>%
transmute(
frecuencia_valoracion = as.character(as_factor(recomp_valorac)),
sexo = as.character(as_factor(`C3P16.1`)),
nivel_educativo = as.character(as_factor(nivel_ed)),
region = as.character(as_factor(region)),
edad = as.numeric(`C0P10.3`),
sector = as.character(as_factor(sector)),
rama_actividad = as.character(as_factor(ramacaes_o))
) %>%
mutate(
# Agrupa la edad numĂ©rica en intervalos de diez años. case_when evalĂșa las
# condiciones en orden; las edades fuera de los intervalos quedan como NA.
rango_etario = case_when(
edad >= 15 & edad <= 19 ~ "15 a 19 años",
edad >= 20 & edad <= 29 ~ "20 a 29 años",
edad >= 30 & edad <= 39 ~ "30 a 39 años",
edad >= 40 & edad <= 49 ~ "40 a 49 años",
edad >= 50 & edad <= 59 ~ "50 a 59 años",
edad >= 60 & edad <= 69 ~ "60 a 69 años",
edad >= 70 & edad <= 79 ~ "70 a 79 años",
edad >= 80 & edad <= 89 ~ "80 a 89 años",
TRUE ~ NA_character_
),
# Resume las siete respuestas originales en cuatro niveles sustantivos:
# Alto, Medio, Bajo y S/R (sin respuesta o no aplicable).
nivel_reconocimiento = case_when(
frecuencia_valoracion %in% c("Siempre", "Muchas veces") ~ "Alto",
frecuencia_valoracion == "Algunas veces" ~ "Medio",
frecuencia_valoracion %in% c("Solo alguna vez", "Nunca") ~ "Bajo",
frecuencia_valoracion %in% c("No corresponde", "Ns/Nc") ~ "S/R",
TRUE ~ NA_character_
),
# Convierte variables a factores y fija su orden. Esto evita que tablas,
# leyendas y ejes se ordenen alfabéticamente o de manera inconsistente.
sexo = factor(sexo, levels = c("VarĂłn", "Mujer")),
nivel_reconocimiento = factor(
nivel_reconocimiento,
levels = c("Alto", "Medio", "Bajo", "S/R")
),
frecuencia_valoracion = factor(
frecuencia_valoracion,
levels = c(
"Siempre",
"Muchas veces",
"Algunas veces",
"Solo alguna vez",
"Nunca",
"No corresponde",
"Ns/Nc"
)
)
) %>%
# Excluye registros sin sexo o sin nivel de reconocimiento clasificable,
# porque no pueden aportar a comparaciones segĂșn sexo.
filter(!is.na(sexo), !is.na(nivel_reconocimiento))
# Colores para los grĂĄficos
colores_reconocimiento <- c(
"Alto" = "#1B9E77",
"Medio" = "#E6AB02",
"Bajo" = "#D95F02",
"S/R" = "#7570B3"
)
# Crea la carpeta de salida solo si no existe; asĂ el documento puede ejecutarse
# varias veces sin producir un error por intentar recrearla.
if (!dir.exists("graficos_reconocimiento")) {
dir.create("graficos_reconocimiento")
}
# Calcula, para cada sexo, la proporciĂłn general de reconocimiento Alto. Esta
# referencia se repetirĂĄ como diamante en cada grĂĄfico desagregado.
referencia_alto_sexo <- base_reconocimiento %>%
filter(nivel_reconocimiento %in% c("Alto", "Medio", "Bajo")) %>%
group_by(sexo) %>%
summarise(
referencia_alto = mean(
as.character(nivel_reconocimiento) == "Alto"
),
.groups = "drop"
)
referencia_alto_sexo
# ------------------------------------------------------------
# 3. Cruce inicial: frecuencia de valoraciĂłn segĂșn sexo
# Se excluyen Ns/Nc y No corresponde del grĂĄfico
# ------------------------------------------------------------
# Tabla para el grĂĄfico: se cuentan casos por sexo y nivel, y los porcentajes
# se calculan dentro de cada sexo solo entre Alto, Medio y Bajo. S/R no entra
# al denominador para no mezclar falta de respuesta con la distribuciĂłn analizada.
tabla_frecuencia_sexo <- base_reconocimiento %>%
filter(nivel_reconocimiento %in% c("Alto", "Medio", "Bajo")) %>%
count(sexo, nivel_reconocimiento, name = "casos") %>%
group_by(sexo) %>%
mutate(
porcentaje = round(100 * casos / sum(casos), 1)
) %>%
ungroup()
tabla_frecuencia_sexo
# Tabla de control: cuantifica los S/R excluidos y qué porcentaje representan
# del total de personas de cada sexo, para transparentar la exclusiĂłn.
tabla_sr_sexo <- base_reconocimiento %>%
filter(nivel_reconocimiento == "S/R") %>%
count(sexo, name = "casos_sin_respuesta") %>%
left_join(
base_reconocimiento %>%
count(sexo, name = "total_respondentes"),
by = "sexo"
) %>%
mutate(
porcentaje_sin_respuesta = round(
100 * casos_sin_respuesta / total_respondentes,
1
)
)
tabla_sr_sexo
# Colores solicitados
colores_grafico <- c(
"Alto" = "#58A65C",
"Medio" = "#A6A6A6",
"Bajo" = "#F4A6B5"
)
# GrĂĄfico de barras apiladas al 100%: cada barra representa la distribuciĂłn de
# niveles de reconocimiento dentro de un sexo; las etiquetas muestran el valor exacto.
grafico_frecuencia_sexo <- ggplot(
tabla_frecuencia_sexo,
aes(x = sexo, y = porcentaje, fill = nivel_reconocimiento)
) +
geom_col(width = 0.65, color = "white", linewidth = 0.6) +
geom_text(
aes(label = paste0(porcentaje, "%")),
position = position_stack(vjust = 0.5),
color = "black",
fontface = "bold",
size = 4
) +
scale_fill_manual(
values = colores_grafico,
breaks = c("Alto", "Medio", "Bajo")
) +
scale_y_continuous(
labels = function(x) paste0(x, "%"),
breaks = seq(0, 100, 25),
expand = c(0, 0)
) +
coord_cartesian(ylim = c(0, 100)) +
labs(
title = "Reconocimiento laboral segĂșn sexo",
subtitle = "Porcentaje dentro de cada sexo",
x = NULL,
y = "Porcentaje",
fill = "Nivel de reconocimiento",
caption = paste(
"Alto: siempre o muchas veces. Medio: algunas veces. Bajo: solo alguna vez o nunca.\n",
"No corresponde y Ns/Nc se excluyen del grĂĄfico; ver tabla de control."
)
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold"),
legend.position = "bottom",
panel.grid.major.x = element_blank(),
plot.caption.position = "plot",
plot.caption = element_text(hjust = 0, size = 8)
)
grafico_frecuencia_sexo
# Exporta la figura en PNG de alta resoluciĂłn para usarla fuera del informe.
ggsave(
"graficos_reconocimiento/01_reconocimiento_segun_sexo.png",
grafico_frecuencia_sexo,
width = 10,
height = 7,
dpi = 300
)
# ============================================================
# 4. FUNCIĂN PARA GRĂFICOS CON BRECHA Y REFERENCIA GENERAL
# ============================================================
colores_grafico <- c(
"Alto" = "#58A65C",
"Medio" = "#A6A6A6",
"Bajo" = "#F4A6B5"
)
crear_grafico_brecha <- function(
base,
variable,
titulo_variable,
orden = NULL,
excluidos = character(0),
archivo,
alto = 9,
tamano_etiquetas = 8,
espaciado_filas = 0.15,
ancho_etiquetas = 18
) {
base_grafico <- base %>%
transmute(
sexo = factor(as.character(sexo), levels = c("VarĂłn", "Mujer")),
grupo = trimws(as.character(.data[[variable]])),
nivel_reconocimiento = factor(
as.character(nivel_reconocimiento),
levels = c("Alto", "Medio", "Bajo")
)
) %>%
filter(!is.na(sexo), !is.na(grupo))
tabla_excluidos <- base_grafico %>%
filter(grupo %in% excluidos) %>%
count(grupo, sexo, name = "casos") %>%
mutate(
porcentaje_muestra = round(100 * casos / nrow(base_grafico), 2)
)
print(tabla_excluidos)
base_grafico <- base_grafico %>%
filter(
!grupo %in% excluidos,
nivel_reconocimiento %in% c("Alto", "Medio", "Bajo")
)
categorias_presentes <- unique(base_grafico$grupo)
if (is.null(orden)) {
orden_final <- sort(categorias_presentes)
} else {
orden_final <- c(
orden[orden %in% categorias_presentes],
setdiff(categorias_presentes, orden)
)
}
base_grafico <- base_grafico %>%
mutate(
grupo = factor(
grupo,
levels = orden_final,
ordered = TRUE
)
)
tabla <- base_grafico %>%
count(grupo, sexo, nivel_reconocimiento, name = "casos") %>%
complete(
grupo,
sexo,
nivel_reconocimiento,
fill = list(casos = 0)
)
tabla_pct <- tabla %>%
group_by(grupo, sexo) %>%
mutate(proporcion = casos / sum(casos)) %>%
ungroup()
df_gap <- tabla_pct %>%
filter(nivel_reconocimiento == "Alto") %>%
select(grupo, sexo, proporcion) %>%
pivot_wider(
names_from = sexo,
values_from = proporcion,
values_fill = 0
) %>%
mutate(
brecha_pp = (`VarĂłn` - Mujer) * 100,
brecha_texto = paste0(
ifelse(brecha_pp > 0, "+", ""),
round(brecha_pp, 1),
" pp"
)
)
df_ovalo <- df_gap %>%
select(grupo, Mujer, `VarĂłn`) %>%
pivot_longer(
cols = c(Mujer, `VarĂłn`),
names_to = "sexo",
values_to = "proporcion_alto"
) %>%
mutate(
sexo = factor(sexo, levels = c("VarĂłn", "Mujer"))
)
df_diamante <- tidyr::expand_grid(
grupo = factor(
levels(tabla$grupo),
levels = levels(tabla$grupo),
ordered = TRUE
),
sexo = factor(
c("VarĂłn", "Mujer"),
levels = c("VarĂłn", "Mujer")
)
) %>%
left_join(
referencia_alto_sexo,
by = "sexo"
)
grafico <- ggplot(
data = tabla,
aes(
x = casos,
y = sexo,
fill = nivel_reconocimiento
)
) +
geom_col(
position = position_fill(reverse = TRUE),
color = "white",
linewidth = 0.4
) +
ggforce::geom_mark_ellipse(
data = df_ovalo,
aes(
x = proporcion_alto,
y = sexo,
group = grupo
),
inherit.aes = FALSE,
color = "#1976D2",
fill = NA,
linewidth = 0.9,
expand = grid::unit(2.5, "mm")
) +
geom_point(
data = df_diamante,
aes(
x = referencia_alto,
y = sexo
),
inherit.aes = FALSE,
shape = 23,
size = 3.8,
stroke = 1,
fill = "#58A65C",
color = "white"
) +
geom_text(
data = df_gap,
aes(
y = "Mujer",
label = brecha_texto
),
x = 1.05,
inherit.aes = FALSE,
hjust = 0,
color = "gray30",
fontface = "bold",
size = 3
) +
facet_grid(
grupo ~ .,
switch = "y",
labeller = labeller(grupo = label_wrap_gen(ancho_etiquetas))
) +
scale_fill_manual(
values = colores_grafico,
breaks = c("Alto", "Medio", "Bajo")
) +
scale_x_continuous(
labels = scales::percent,
breaks = seq(0, 1, by = 0.25),
expand = c(0, 0)
) +
coord_cartesian(
xlim = c(0, 1.15),
clip = "off"
) +
guides(
fill = guide_legend(order = 1)
) +
labs(
title = paste(
"Nivel de reconocimiento laboral segĂșn sexo\ny",
tolower(titulo_variable)
),
subtitle = paste(
"DistribuciĂłn porcentual dentro de cada sexo y",
tolower(titulo_variable)
),
x = "Porcentaje",
y = NULL,
fill = "Nivel de reconocimiento",
caption = paste(
"Alto: siempre o muchas veces. Medio: algunas veces. Bajo: solo alguna vez o nunca.\n",
"Los Ăłvalos azules y los valores en pp indican la brecha de reconocimiento Alto ",
"(diferencia entre VarĂłn y Mujer).\n",
"El diamante verde representa el promedio general de reconocimiento Alto para cada sexo."
)
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(
face = "bold",
size = 14,
lineheight = 0.9
),
legend.position = "bottom",
strip.text.y.left = element_text(
angle = 0,
face = "bold",
size = tamano_etiquetas,
lineheight = 0.8,
margin = margin(r = 10)
),
strip.placement = "outside",
axis.text.y = element_text(size = 8),
panel.grid.major.y = element_blank(),
panel.spacing.y = grid::unit(espaciado_filas, "lines"),
plot.caption.position = "plot",
plot.caption = element_text(hjust = 0, size = 8)
)
print(grafico)
ggsave(
paste0("graficos_reconocimiento/", archivo),
grafico,
width = 12,
height = alto,
dpi = 300
)
return(
list(
tabla = tabla,
tabla_excluidos = tabla_excluidos,
brechas = df_gap,
grafico = grafico
)
)
}
# ============================================================
# ĂRDENES DE LAS CATEGORĂAS
# ============================================================
orden_nivel_educativo <- c(
"Posgrado completo",
"Posgrado incompleto",
"Universitario completo",
"Universitario incompleto",
"Terciario completo",
"Terciario incompleto",
"Secundario completo",
"Secundario incompleto",
"Primario completo",
"Primario incompleto",
"Sin instrucciĂłn"
)
orden_region <- c(
"Gran Buenos Aires",
"Pampeana",
"NOA",
"NEA",
"Patagonia",
"Cuyo"
)
orden_rango_etario <- c(
"80 a 89 años",
"70 a 79 años",
"60 a 69 años",
"50 a 59 años",
"40 a 49 años",
"30 a 39 años",
"20 a 29 años",
"15 a 19 años"
)
orden_sector <- c(
"Privado",
"PĂșblico o estatal",
"De otro tipo"
)
orden_rama_actividad <- c(
"Actividades primarias",
"Industria manufacturera",
"ConstrucciĂłn",
"Comercio",
"Hoteles y restaurantes",
"Transporte, alm y comunic",
"Serv financ, inm, alq y emp",
"AdministraciĂłn pĂșblica y defensa",
"Enseñanza",
"Servicios sociales y de salud",
"Otros serv comunit, soc y per",
"Trabajo doméstico",
"Otras ramas"
)
# ============================================================
# GRĂFICOS
# ============================================================
resultado_nivel_educativo <- crear_grafico_brecha(
base = base_reconocimiento,
variable = "nivel_educativo",
titulo_variable = "Nivel educativo",
orden = orden_nivel_educativo,
excluidos = c("Ns/Nc", "S/R"),
archivo = "02_reconocimiento_sexo_nivel_educativo.png",
alto = 14
)
## # A tibble: 2 Ă 4
## grupo sexo casos porcentaje_muestra
## <chr> <fct> <int> <dbl>
## 1 Ns/Nc VarĂłn 6 0.07
## 2 Ns/Nc Mujer 6 0.07
resultado_region <- crear_grafico_brecha(
base = base_reconocimiento,
variable = "region",
titulo_variable = "RegiĂłn",
orden = orden_region,
archivo = "03_reconocimiento_sexo_region.png",
alto = 8
)
## # A tibble: 0 Ă 4
## # âč 4 variables: grupo <chr>, sexo <fct>, casos <int>, porcentaje_muestra <dbl>
resultado_rango_etario <- crear_grafico_brecha(
base = base_reconocimiento,
variable = "rango_etario",
titulo_variable = "Rango etario",
orden = orden_rango_etario,
archivo = "04_reconocimiento_sexo_rango_etario.png",
alto = 10
)
## # A tibble: 0 Ă 4
## # âč 4 variables: grupo <chr>, sexo <fct>, casos <int>, porcentaje_muestra <dbl>
resultado_sector <- crear_grafico_brecha(
base = base_reconocimiento,
variable = "sector",
titulo_variable = "Sector de ocupaciĂłn",
orden = orden_sector,
excluidos = c("Ns/Nc", "S/R"),
archivo = "05_reconocimiento_sexo_sector.png",
alto = 7
)
## # A tibble: 2 Ă 4
## grupo sexo casos porcentaje_muestra
## <chr> <fct> <int> <dbl>
## 1 Ns/Nc VarĂłn 1 0.01
## 2 Ns/Nc Mujer 2 0.02
resultado_rama_actividad <- crear_grafico_brecha(
base = base_reconocimiento,
variable = "rama_actividad",
titulo_variable = "Rama de actividad",
orden = orden_rama_actividad,
excluidos = c("Sin especificar", "Ns/Nc", "S/R"),
archivo = "06_reconocimiento_sexo_rama_actividad.png",
alto = 16,
tamano_etiquetas = 7,
espaciado_filas = 0.15,
ancho_etiquetas = 30
)
## # A tibble: 2 Ă 4
## grupo sexo casos porcentaje_muestra
## <chr> <fct> <int> <dbl>
## 1 Sin especificar VarĂłn 17 0.19
## 2 Sin especificar Mujer 6 0.07