# ============================================================
# CARGA DE LIBRERÍAS
# ============================================================
library(tidyverse)
library(ggplot2)
library(plotly)
library(DT)
library(knitr)
library(rmarkdown)
library(scales)
library(readxl)   # lectura directa del archivo .xlsx
# ============================================================
# CARGA Y LIMPIEZA DE DATOS
# Lee directamente desde el archivo .xlsx -- no se necesitan CSVs
# IMPORTANTE: ajuste la ruta al .xlsx si el archivo esta en otra carpeta
# ============================================================

ARCHIVO_XLSX <- "C:/Users/User/Downloads/BASES DE DATOS UNIFICADAS (1).xlsx"  # <-- cambie solo esta linea si es necesario

# Verifica que el archivo exista y muestra un mensaje claro si no
if (!file.exists(ARCHIVO_XLSX)) {
  stop(paste0(
    "No se encontro el archivo: '", ARCHIVO_XLSX, "'\n",
    "Directorio de trabajo actual: ", getwd(), "\n",
    "Coloque el archivo .xlsx en esa carpeta o ajuste la variable ARCHIVO_XLSX."
  ))
}

# --- Helper: normaliza nombres de columna ---
limpiar_nombres <- function(df) {
  names(df) <- trimws(gsub("\n", " ", names(df)))
  df
}

# --- Helper: convierte tasa decimal (0-1) a porcentaje (0-100) fila por fila ---
# Usa el maximo de toda la columna para decidir, no dentro de mutate por fila
normalizar_tasa <- function(x) {
  if (max(x, na.rm = TRUE) <= 1) x * 100 else x
}

# 1) 23 Ciudades (trimestral) -- hoja: "23 ciudades "
# FILTROS CRITICOS:
#   a) Excluir filas de totales agregados ("Total 23 ciudades...", etc.)
#   b) Excluir filas donde Ciudad esta vacia
df_ciudades <- read_excel(ARCHIVO_XLSX, sheet = "23 ciudades ") |>
 limpiar_nombres()
df_ciudades$Ciudad  <- trimws(df_ciudades$Ciudad)
df_ciudades$Año     <- as.integer(df_ciudades$Año)
df_ciudades$Periodo <- paste(df_ciudades$Año, df_ciudades$Trimestre, sep = " - ")

# Eliminar filas de totales y filas sin ciudad
df_ciudades <- df_ciudades |>
  filter(
    !is.na(Ciudad),
    Ciudad != "",
    !grepl("^[Tt]otal", Ciudad)   # excluye "Total 23 ciudades...", "Total 13...", etc.
  ) |>
  mutate(
    `Tasa de Ocupación (TO)`    = normalizar_tasa(`Tasa de Ocupación (TO)`),
    `Tasa de Desocupación (TD)` = normalizar_tasa(`Tasa de Desocupación (TD)`)
  )

# 2) Total Nacional (mensual) -- hoja: "Total_Nacional"
df_nacional <- read_excel(ARCHIVO_XLSX, sheet = "Total_Nacional") |>
  limpiar_nombres()
df_nacional$Año <- as.integer(df_nacional$Año)

# Normalizar tasas antes de promediar (fila por fila sobre columna completa)
df_nacional <- df_nacional |>
  mutate(
    `Tasa de Ocupación (TO)`    = normalizar_tasa(`Tasa de Ocupación (TO)`),
    `Tasa de Desocupación (TD)` = normalizar_tasa(`Tasa de Desocupación (TD)`)
  )

# Promedio anual -- solo años con 12 meses completos para cifras exactas
# Se calcula cuantos registros tiene cada año y se excluye el ultimo si esta incompleto
conteo_meses <- df_nacional |> count(Año)
meses_max    <- max(conteo_meses$n)
anios_completos <- conteo_meses$Año[conteo_meses$n >= meses_max * 0.9]

df_nac_anual <- df_nacional |>
  group_by(Año) |>
  summarise(
    `Fuerza de trabajo`         = mean(`Fuerza de trabajo`,         na.rm = TRUE),
    `Población ocupada`         = mean(`Población ocupada`,         na.rm = TRUE),
    `Población desocupada`      = mean(`Población desocupada`,      na.rm = TRUE),
    `Tasa de Ocupación (TO)`    = mean(`Tasa de Ocupación (TO)`,    na.rm = TRUE),
    `Tasa de Desocupación (TD)` = mean(`Tasa de Desocupación (TD)`, na.rm = TRUE),
    n_meses                     = n(),
    .groups = "drop"
  )

# 3) Pobreza Monetaria — hoja: "PobrezaMonetaria"
# readxl preserva \n en nombres de columna; se renombran por posicion para evitar
# problemas de grep con espacios dobles o saltos residuales.
df_pobreza_raw <- read_excel(ARCHIVO_XLSX, sheet = "PobrezaMonetaria",
                             col_names = FALSE, skip = 1)
names(df_pobreza_raw) <- c("Año", "Poblacion_Nacional_miles",
                           "Personas_Pobreza_miles", "Tasa_Pobreza_pct",
                           "Reduccion_pp", "Var_Personas_miles")
df_pobreza <- df_pobreza_raw |>
  mutate(
    Año                    = suppressWarnings(as.integer(Año)),
    Personas_Pobreza_miles = suppressWarnings(as.numeric(Personas_Pobreza_miles)),
    Tasa_Pobreza_pct       = suppressWarnings(as.numeric(Tasa_Pobreza_pct))
  ) |>
  filter(!is.na(Año), !is.na(Tasa_Pobreza_pct))

# Variables de referencia usadas en los graficos de pobreza
col_tasa     <- "Tasa_Pobreza_pct"
col_personas <- "Personas_Pobreza_miles"

# Normalizar: si la tasa viene como decimal (0–1) convertir a porcentaje (0–100)
if (max(df_pobreza[[col_tasa]], na.rm = TRUE) <= 1) {
  df_pobreza[[col_tasa]] <- df_pobreza[[col_tasa]] * 100
}

# 4) Género — hoja: "Genero"
df_genero <- read_excel(ARCHIVO_XLSX, sheet = "Genero") |>
  limpiar_nombres()
df_genero$Año <- as.integer(df_genero$Año)

df_gen_anual <- df_genero |>
  mutate(
    `Tasa Global de Participación (TGP)` = normalizar_tasa(`Tasa Global de Participación (TGP)`),
    `Tasa de Ocupación (TO)`             = normalizar_tasa(`Tasa de Ocupación (TO)`),
    `Tasa de Desocupación (TD)`          = normalizar_tasa(`Tasa de Desocupación (TD)`)
  ) |>
  group_by(Año, `SEXO + TOTAL`) |>
  summarise(
    TGP = mean(`Tasa Global de Participación (TGP)`, na.rm = TRUE),
    TO  = mean(`Tasa de Ocupación (TO)`,             na.rm = TRUE),
    TD  = mean(`Tasa de Desocupación (TD)`,          na.rm = TRUE),
    .groups = "drop"
  ) |>
  pivot_longer(c(TGP, TO, TD), names_to = "Indicador", values_to = "Valor")

# 5) SMLV vs Fuerza de Trabajo — hoja: "SMLV_FuerzaTrabajo"
df_smlv <- read_excel(ARCHIVO_XLSX, sheet = "SMLV_FuerzaTrabajo") |>
  limpiar_nombres()

# Renombrar columnas de forma robusta
ft_col <- grep("Fuerza de trabajo", names(df_smlv), value = TRUE)[1]
sm_col <- grep("Salario [Mm]in",    names(df_smlv), value = TRUE)[1]
names(df_smlv)[names(df_smlv) == ft_col] <- "FuerzaTrabajo"
names(df_smlv)[names(df_smlv) == sm_col] <- "SalarioMinimo"
df_smlv <- df_smlv |>
  mutate(
    FuerzaTrabajo = suppressWarnings(as.numeric(FuerzaTrabajo)),
    SalarioMinimo = suppressWarnings(as.numeric(SalarioMinimo))
  ) |>
  filter(!is.na(FuerzaTrabajo), !is.na(SalarioMinimo))

Análisis de Evolución Socioeconómica en Colombia

Informe Académico de Análisis de Datos


Servicio Nacional de Aprendizaje — SENA

Período de análisis: 2010 – 2025  |  Fuente: DANE – GEIH

03 de julio de 2026


1 Introducción

Colombia es un país en permanente transformación socioeconómica. Desde la primera década del siglo XXI, el país ha experimentado cambios estructurales en su mercado laboral, impulsados por el crecimiento económico, las reformas institucionales, los choques externos como la pandemia de COVID-19 en 2020 y las políticas de protección social.

El presente informe analiza la evolución de los principales indicadores del mercado laboral y la pobreza monetaria en Colombia durante el período 2010–2025, utilizando datos oficiales del Departamento Administrativo Nacional de Estadística (DANE), obtenidos a través de la Gran Encuesta Integrada de Hogares (GEIH).

Nota metodológica: Todos los indicadores de tasas se expresan en porcentaje (%). Las cifras de población se expresan en miles de personas, conforme a la presentación original del DANE.

El análisis abarca cinco dimensiones complementarias:

  1. El comportamiento del mercado laboral a nivel nacional.
  2. Las diferencias territoriales entre 23 ciudades principales y sus áreas metropolitanas.
  3. La evolución de la pobreza monetaria.
  4. Las brechas de género en los indicadores laborales.
  5. La relación entre el Salario Mínimo Legal Vigente (SMLV) y la fuerza laboral.

2 Objetivos

2.1 Objetivo General

Analizar la evolución de los indicadores socioeconómicos de Colombia entre 2010 y 2026, identificando tendencias, brechas y factores de cambio en el mercado laboral y la pobreza monetaria.

2.2 Objetivos Específicos

  • OE1. Describir la trayectoria de la Fuerza de Trabajo, la Población Ocupada y la Población Desocupada a nivel nacional.
  • OE2. Comparar la Tasa de Ocupación (TO) y la Tasa de Desocupación (TD) entre 23 ciudades y áreas metropolitanas.
  • OE3. Examinar la evolución de la pobreza monetaria, en términos de tasa y de número de personas.
  • OE4. Identificar las brechas de género en la participación y ocupación laboral.
  • OE5. Evaluar la correlación entre el incremento del Salario Mínimo y el tamaño de la Fuerza de Trabajo.

3 Metodología

3.1 Fuentes de Datos

Módulo Fuente Cobertura temporal Periodicidad
Mercado laboral nacional DANE – GEIH 2010–2026 Mensual
23 ciudades AM DANE – GEIH 2010–2026 Trimestral
Pobreza monetaria DANE – Informe oficial 2012–2023 Anual
Género DANE – GEIH 2010–2025 Mensual
SMLV Ministerio del Trabajo / DANE 2010–2024 Anual

3.2 Tratamiento de los Datos

Los datos fueron procesados en R (4.6.0) mediante el ecosistema tidyverse. El preprocesamiento incluyó:

  • Normalización de nombres de columna (eliminación de saltos de línea y espacios).
  • Conversión de tipos de dato (enteros, numérico, carácter).
  • Agregación temporal: los datos mensuales se promediaron por año para facilitar la comparación longitudinal.
  • Las tasas originales en formato decimal (0–1) se multiplicaron por 100 para expresarlas en porcentaje.

3.3 Indicadores Clave

Tabla 1. Definición de indicadores utilizados en el análisis.
Indicador Sigla Definición
Tasa Global de Participación TGP Porcentaje de la PET que hace parte de la Fuerza de Trabajo.
Tasa de Ocupación TO Porcentaje de la PET que se encuentra empleada.
Tasa de Desocupación TD Porcentaje de la Fuerza de Trabajo que no tiene empleo y lo busca activamente.
Fuerza de Trabajo FT Suma de Población Ocupada y Población Desocupada (miles de personas).
Tasa de Pobreza Monetaria TPM Porcentaje de personas con ingresos por debajo de la línea de pobreza.

4 Análisis del Mercado Laboral Nacional

4.1 Resumen de Indicadores Clave

26,153
Fuerza de Trabajo 2025 (miles)
58.6%
Tasa de Ocupación 2025
8.9%
Tasa de Desocupación 2025
16 años
Período analizado

4.2 Evolución de la Fuerza de Trabajo, Población Ocupada y Desocupada

df_nac_largo <- df_nac_anual |>
  select(Año, `Fuerza de trabajo`, `Población ocupada`, `Población desocupada`) |>
  pivot_longer(-Año, names_to = "Variable", values_to = "Valor")

## Nota de legibilidad: en la version original las 3 series usaban tonos de azul
## muy cercanos entre si (dificiles de distinguir, especialmente para personas
## con daltonismo). Se usa un color de alto contraste (NARANJA) para la
## Poblacion Desocupada, ya que es la serie mas relevante para el diagnostico.
pal_nac <- c(
  "Fuerza de trabajo"    = AZUL_DESTACADOS,
  "Población ocupada"    = AZUL_PRINCIPAL,
  "Población desocupada" = NARANJA
)

p_nac <- ggplot(df_nac_largo, aes(x = Año, y = Valor / 1000,
                                   color = Variable, group = Variable)) +
  geom_line(linewidth = 1.6) +
  geom_point(size = 2.8, shape = 21, fill = "white", stroke = 1.5) +
  scale_color_manual(values = pal_nac, name = "") +
  scale_y_continuous(labels = scales::label_comma(suffix = " M")) +
  scale_x_continuous(breaks = seq(min(df_nac_anual$Año),
                                   max(df_nac_anual$Año), by = 2)) +
  labs(title    = "Evolución del Mercado Laboral Nacional",
       subtitle = "Promedio anual — miles de personas",
       x = "Año", y = "Millones de personas",
       caption = "Fuente: DANE — Gran Encuesta Integrada de Hogares (GEIH)") +
  tema_corporativo

ggplotly(p_nac, tooltip = c("x", "y", "colour")) |>
  layout(
    paper_bgcolor = FONDO_APP,
    plot_bgcolor  = "#FFFFFF",
    margin = list(l = 60, r = 60, t = 80, b = 80),
    legend = list(orientation = "h", x = 0.2, y = -0.2)
  ) |>
  centrar_grafico()

Diagnóstico del gráfico — Figura 1

Tipo de gráfico: líneas múltiples con marcadores (serie de tiempo).

¿Por qué este tipo de gráfico? Se usa una serie de tiempo de líneas porque el objetivo es mostrar la evolución continua de tres variables numéricas (Fuerza de Trabajo, Población Ocupada y Población Desocupada) a lo largo de los años. Las líneas permiten identificar tendencias, puntos de quiebre y la relación de crecimiento paralelo entre las tres series, algo que un gráfico de barras dificultaría al comparar 16 años simultáneamente. El color naranja resalta la Población Desocupada, que es la serie con menor magnitud pero mayor relevancia analítica.

Lectura diagnóstica: las tres curvas muestran una tendencia creciente y casi paralela hasta 2019, lo que indica que el crecimiento de la Fuerza de Trabajo fue absorbido mayoritariamente por la Población Ocupada. El quiebre de 2020 es visible como una discontinuidad en la pendiente de la Población Desocupada, coherente con el choque pandémico.

4.3 Tasas de Ocupación y Desocupación Nacionales

library(dplyr)
library(tidyr)
library(ggplot2)
library(plotly)
library(scales)

# 🔹 Transformación de datos
df_tasas_largo <- df_nac_anual |>
  select(Año, `Tasa de Ocupación (TO)`, `Tasa de Desocupación (TD)`) |>
  pivot_longer(
    cols = -Año,
    names_to = "Tasa",
    values_to = "Valor"
  )

# 🔹 Colores
pal_tasas <- c(
  "Tasa de Ocupación (TO)"    = AZUL_PRINCIPAL,
  "Tasa de Desocupación (TD)" = AZUL_DESTACADOS
)

# 🔹 Gráfico base
p_tasas <- ggplot(df_tasas_largo, aes(
  x = Año,
  y = Valor,
  color = Tasa,
  group = Tasa
)) +

  # Área sombreada (solo desempleo)
  geom_ribbon(
    data = df_tasas_largo |> filter(Tasa == "Tasa de Desocupación (TD)"),
    aes(ymin = 0, ymax = Valor),
    fill = AZUL_DESTACADOS,
    alpha = 0.12,
    color = NA
  ) +

  # Líneas
  geom_line(linewidth = 1.6) +

  # Puntos
  geom_point(size = 3, shape = 21, fill = "white", stroke = 1.2) +

  # Colores
  scale_color_manual(values = pal_tasas, name = "") +

  # Formato porcentaje
  scale_y_continuous(labels = label_percent(scale = 1, suffix = "%")) +

  # Eje X (años ordenados)
  scale_x_continuous(
    breaks = seq(min(df_nac_anual$Año),
                 max(df_nac_anual$Año),
                 by = 2)
  ) +

  # Etiquetas
  labs(
    title = "Tasas de Ocupación y Desocupación — Colombia",
    subtitle = "Promedio anual (%)",
    x = "Año",
    y = "Tasa (%)",
    caption = "Fuente: DANE — GEIH"
  ) +

  # Tema corporativo
  tema_corporativo +

  theme(
    legend.position = "bottom",
    legend.direction = "horizontal",
    plot.margin = margin(t = 20, r = 20, b = 20, l = 20)
  )

# 🔹 Convertir a interactivo (Plotly)
ggplotly(p_tasas, tooltip = c("x", "y", "colour")) |>
  layout(
    paper_bgcolor = FONDO_APP,
    plot_bgcolor = "#FFFFFF",
    margin = list(l = 60, r = 60, t = 80, b = 80),
    legend = list(orientation = "h", x = 0.2, y = -0.2)
  ) |>
  centrar_grafico()

Diagnóstico del gráfico — Figura 2

Tipo de gráfico: líneas dobles con área sombreada (serie de tiempo, dos tasas en %).

¿Por qué este tipo de gráfico? Al tratarse de dos tasas expresadas en la misma unidad (%), el gráfico de líneas permite compararlas directamente en la misma escala del eje Y. El área sombreada bajo la TD es un recurso visual adicional (no un tercer gráfico) que refuerza la lectura del desempleo como la variable de mayor interés del módulo, sin sacrificar la comparabilidad con la TO.

Lectura diagnóstica: la TO se mantiene consistentemente por encima de la TD durante todo el período, lo cual es esperable (la TD es un subconjunto de la Fuerza de Trabajo). El área sombreada permite detectar visualmente, sin necesidad de leer valores exactos, el momento y la magnitud del repunte de desempleo de 2020.

4.4 Tabla de Datos — Mercado Laboral Nacional

df_nac_anual |>
  mutate(across(c(`Fuerza de trabajo`, `Población ocupada`, `Población desocupada`),
                ~ scales::comma(round(., 0))),
         across(c(`Tasa de Ocupación (TO)`, `Tasa de Desocupación (TD)`),
                ~ paste0(round(., 1), "%"))) |>
  select(Año, `Fuerza de trabajo`, `Población ocupada`, `Población desocupada`,
         `Tasa de Ocupación (TO)`, `Tasa de Desocupación (TD)`) |>
  DT::datatable(
    caption   = "Tabla 2. Indicadores del Mercado Laboral Nacional — Promedio anual.",
    rownames  = FALSE,
    filter    = "top",
    extensions = "Buttons",
    options   = list(
      dom        = "Bfrtip",
      buttons    = c("csv", "excel"),
      pageLength = 10,
      language   = list(url = "//cdn.datatables.net/plug-ins/1.10.11/i18n/Spanish.json")
    )
  )

4.5 Interpretación

Hallazgos principales del mercado laboral nacional:

  • La Fuerza de Trabajo en Colombia mostró una tendencia de crecimiento sostenido entre 2010 y 2019, alcanzando 23.9 millones de personas antes de la pandemia, lo que refleja el dinamismo demográfico y la incorporación progresiva de la población al mercado laboral.

  • La crisis por COVID-19 en 2020 generó una ruptura estructural severa: la Tasa de Desocupación alcanzó su máximo histórico del período con 16.7% en 2020, evidenciando la vulnerabilidad del mercado laboral colombiano ante choques externos.

  • La recuperación post-pandémica fue notable en términos de Población Ocupada, pero la Tasa de Desocupación se mantuvo por encima de los niveles prepandémicos (TO 2019: 57.7% vs. TO 2025: 58.6%), sugiriendo la persistencia de informalidad y subempleo.

  • La Tasa de Desocupación al inicio del período (2010) era de 12%, y en 2025 se sitúa en 8.9%, reflejando el balance de la evolución estructural del mercado laboral.


5 Análisis de las 23 Ciudades y Áreas Metropolitanas

5.1 Tasa de Desocupación por Ciudad (promedio anual)

anio_max_ciu   <- max(df_ciudades$Año)
anio_inicio_ciu <- max(anio_max_ciu - 4, min(df_ciudades$Año))

df_ciu_resumen <- df_ciudades |>
  filter(Año >= anio_inicio_ciu) |>
  group_by(Ciudad) |>
  summarise(
    TO_prom = mean(`Tasa de Ocupación (TO)`,    na.rm = TRUE),
    TD_prom = mean(`Tasa de Desocupación (TD)`, na.rm = TRUE),
    .groups = "drop"
  ) |>
  arrange(desc(TD_prom)) |>
  mutate(Ciudad = factor(Ciudad, levels = Ciudad))

# Separación fija para las etiquetas (proporcional al valor máximo,
# así se ve pareja en todas las barras, cortas y largas)
offset_etiqueta <- max(df_ciu_resumen$TD_prom, na.rm = TRUE) * 0.035

p_ciu_td <- ggplot(df_ciu_resumen,
                    aes(x = TD_prom, y = Ciudad, fill = TD_prom)) +
  geom_col(width = 0.65, show.legend = FALSE) +
  geom_text(aes(x = TD_prom + offset_etiqueta,
                label = paste0(round(TD_prom, 1), "%")),
            hjust = 0, size = 3.4, color = TEXTO) +
  scale_fill_gradient(low = AZUL_CLARO, high = AZUL_PRINCIPAL) +
  scale_x_continuous(expand = expansion(mult = c(0, 0.20)),
                     labels = scales::label_percent(scale = 1, suffix = "%")) +
  labs(title    = "Tasa de Desocupación (TD) por Ciudad",
       subtitle = paste0("Promedio ", anio_inicio_ciu, "–", anio_max_ciu,
                         " — Áreas Metropolitanas"),
       x = "TD Promedio (%)", y = NULL,
       caption = "Fuente: DANE — GEIH") +
  tema_corporativo +
  theme(panel.grid.major.y = element_blank(),
        axis.text.y = element_text(size = 12))

ggplotly(p_ciu_td, tooltip = c("x", "y")) |>
  layout(paper_bgcolor = FONDO_APP, plot_bgcolor = "#FFFFFF") |>
  centrar_grafico()

Diagnóstico del gráfico — Figura 3

Tipo de gráfico: barras horizontales ordenadas, con codificación de color por intensidad (gradiente).

¿Por qué este tipo de gráfico? Con 23 categorías (ciudades), las barras horizontales son preferibles a las verticales porque los nombres de ciudad son largos y no caben legibles en el eje X sin rotarlos. Ordenar de mayor a menor TD convierte al gráfico en un ranking, facilitando identificar de inmediato las ciudades con peor desempeño. El gradiente de color refuerza (sin reemplazar) la codificación por posición, ayudando a distinguir rápidamente los extremos.

Lectura diagnóstica: la dispersión entre la ciudad con mayor y menor TD evidencia heterogeneidad territorial marcada; la posición de cada barra respecto al promedio nacional (Figura 2) permite ubicar a cada ciudad por encima o por debajo del comportamiento agregado del país.

5.2 Tasa de Ocupación por Ciudad

offset_etiqueta_to <- max(df_ciu_resumen$TO_prom, na.rm = TRUE) * 0.05

p_ciu_to <- df_ciu_resumen |>
  arrange(desc(TO_prom)) |>
  mutate(Ciudad = factor(Ciudad, levels = Ciudad)) |>
  ggplot(aes(x = TO_prom, y = Ciudad, fill = TO_prom)) +
  geom_col(width = 0.65, show.legend = FALSE) +
  geom_text(aes(x = TO_prom + offset_etiqueta_to,
                label = paste0(round(TO_prom, 1), "%")),
            hjust = 0, size = 3.4, color = TEXTO, fontface = "bold") +
  scale_fill_gradient(low = AZUL_CLARO, high = AZUL_PRINCIPAL) +
  scale_x_continuous(expand = expansion(mult = c(0, 0.30)),
                     labels = scales::label_percent(scale = 1, suffix = "%")) +
  coord_cartesian(clip = "off") +
  labs(title    = "Tasa de Ocupación (TO) por Ciudad",
       subtitle = paste0("Promedio ", anio_inicio_ciu, "–", anio_max_ciu,
                         " — Áreas Metropolitanas"),
       x = "TO Promedio (%)", y = NULL,
       caption = "Fuente: DANE — GEIH") +
  tema_corporativo +
  theme(panel.grid.major.y = element_blank(),
        axis.text.y = element_text(size = 12),
        plot.margin = margin(t = 10, r = 40, b = 10, l = 10))

ggplotly(p_ciu_to, tooltip = c("x", "y")) |>
  layout(paper_bgcolor = FONDO_APP, plot_bgcolor = "#FFFFFF",
         margin = list(r = 60)) |>
  centrar_grafico()

Diagnóstico del gráfico — Figura 4

Tipo de gráfico: barras horizontales ordenadas (ranking), mismo diseño que la Figura 3 para permitir comparación directa entre ambas.

¿Por qué este tipo de gráfico? Se mantiene deliberadamente el mismo formato visual que la Figura 3 (barras horizontales, mismo orden por categoría) para que el lector pueda comparar visualmente TD y TO ciudad por ciudad sin tener que reinterpretar un tipo de gráfico distinto. Esta consistencia entre figuras es una buena práctica de diseño de reportes.

Lectura diagnóstica: las ciudades que encabezan este ranking (mayor TO) tienden a coincidir con las que muestran menor TD en la Figura 3, confirmando la relación inversa esperada entre ambos indicadores.

5.3 Trayectoria de la Tasa de Desempleo Nacional: Periodo 2010 - 2025

# 1. Cargar las librerías necesarias
library(ggplot2)
library(plotly)
library(dplyr)

# 2. Construir el dataset A PARTIR DE LOS DATOS REALES cargados del .xlsx
# (df_nac_anual, calculado en el chunk 'carga_datos'). Antes este gráfico usaba
# una tabla de valores escritos a mano que no coincidía con el archivo fuente;
# se corrige para que sea coherente con la Figura 2 y con el resto del informe.
datos <- df_nac_anual |>
  transmute(anio = Año, tasa = round(`Tasa de Desocupación (TD)`, 1))

# El año atípico se identifica dinámicamente (no queda "quemado" en el código):
# corresponde al año de mayor TD del período, calculado más arriba en el
# chunk 'interp_nacional' (anio_pico_td).
# Colores dentro de la paleta corporativa: AZUL_DESTACADOS para años normales,
# ROJO_ALERTA para el año atípico (pico pandémico) — mantiene coherencia
# visual con el resto del informe en lugar de colores ajenos a la paleta.
datos <- datos %>%
  mutate(
    color_barra = ifelse(anio == anio_pico_td, ROJO_ALERTA, AZUL_DESTACADOS),
    texto_hover = paste0("Año: ", anio, "<br>Tasa: ", format(tasa, decimal.mark = ","), "%")
  )

# 3. Crear el gráfico base con ggplot2
# Todas las barras muestran su etiqueta (se eliminó el filtro de años fijos,
# que dejaba años sin dato visible y no se adaptaba si cambia el rango del
# archivo fuente).
p <- ggplot(datos, aes(x = factor(anio), y = tasa, fill = color_barra, text = texto_hover)) +
  geom_bar(stat = "identity", width = 0.8) +

  geom_text(
    aes(y = tasa + max(datos$tasa, na.rm = TRUE) * 0.03,
        label = paste0(format(tasa, decimal.mark = ","), "%")),
    vjust = 0,
    fontface = "bold",
    size = 3.4,
    color = TEXTO
  ) +

  scale_fill_identity() +
  labs(
    title    = "Promedio Anual de la Tasa de Desempleo Nacional",
    subtitle = paste0(min(datos$anio), "–", max(datos$anio),
                      " · Año resaltado: ", anio_pico_td,
                      " (pico histórico del período)"),
    x = NULL,
    y = NULL,
    caption = "Fuente: DANE — GEIH"
  ) +
  scale_y_continuous(limits = c(0, max(datos$tasa, na.rm = TRUE) * 1.15)) +
  tema_corporativo +
  theme(
    axis.text.x        = element_text(angle = 35, hjust = 1, vjust = 1, face = "bold"),
    axis.text.y         = element_blank(),
    panel.grid.major    = element_blank(),
    panel.grid.minor    = element_blank(),
    legend.position      = "none"
  )

# 4. Convertir a gráfico interactivo con Plotly
grafico_interactivo <- ggplotly(p, tooltip = "text") %>%
  layout(paper_bgcolor = FONDO_APP, plot_bgcolor = "#FFFFFF") %>%
  config(displayModeBar = FALSE)

# 5. Centrar y mostrar el gráfico
centrar_grafico(grafico_interactivo)

Diagnóstico del gráfico — Figura 5

Tipo de gráfico: barras verticales de serie de tiempo con un valor atípico resaltado por color.

¿Por qué este tipo de gráfico? Aunque la Figura 2 ya muestra la TD como línea, aquí se usan barras porque el objetivo específico de esta figura es destacar un único año atípico (el pico pandémico) frente al resto del período. Las barras facilitan comparar magnitudes año a año como bloques discretos, y el resaltado por color (rojo vs. azul corporativo) dirige la atención inmediatamente al quiebre estructural, algo menos evidente en una línea continua.

Lectura diagnóstica: la altura de la barra roja frente a las azules cuantifica visualmente la magnitud del choque pandémico en el desempleo; las barras posteriores, aunque decrecientes, no vuelven a la altura mínima previa, señal de una recuperación incompleta.

5.4 Interpretación

Hallazgos principales del análisis territorial:

  • Existe una heterogeneidad territorial significativa: la brecha entre la ciudad con mayor y menor Tasa de Desocupación es de 17.3 puntos porcentuales (Quibdó con 26.2% vs. Bucaramanga con 8.9%), lo que refleja diferencias estructurales en las economías locales.

  • Las ciudades con mayor diversificación económica (Bogotá D.C. lidera con una TO de 62.8%) tienden a mostrar Tasas de Ocupación más altas y Tasas de Desocupación más bajas.

  • El impacto del COVID-19 fue generalizado pero diferencial por ciudad, siendo más pronunciado en aquellas con mayor dependencia del sector servicios y comercio informal.

  • La correlación negativa entre TO y TD confirma que ambas tasas capturan fenómenos complementarios, aunque no perfectamente opuestos debido al comportamiento de la TGP.


6 Análisis de Pobreza Monetaria

6.1 Evolución de la Tasa de Pobreza

# Dos paneles separados — evita el problema del eje secundario mal escalado
offset_etiqueta_pobreza <- diff(range(df_pobreza[[col_tasa]], na.rm = TRUE)) * 0.12

p_pobreza_tasa <- ggplot(df_pobreza, aes(x = Año, y = .data[[col_tasa]])) +
  geom_area(fill = AZUL_CLARO, alpha = 0.18) +
  geom_line(color = AZUL_PRINCIPAL, linewidth = 1.1) +
  geom_point(color = AZUL_PRINCIPAL, size = 2.6) +
  geom_text(aes(y = .data[[col_tasa]] + offset_etiqueta_pobreza,
                label = paste0(round(.data[[col_tasa]], 1), "%")),
            size = 3.3, color = TEXTO, fontface = "bold") +
  scale_y_continuous(labels = scales::label_percent(scale = 1, suffix = "%"),
                      expand = expansion(mult = c(0.05, 0.22))) +
  scale_x_continuous(breaks = df_pobreza$Año) +
  labs(title    = "Evolución de la Tasa de Pobreza Monetaria",
       subtitle = paste0("Colombia, ", min(df_pobreza$Año), "–", max(df_pobreza$Año)),
       x = NULL, y = "Tasa de Pobreza (%)",
       caption = "Fuente: DANE") +
  tema_corporativo +
  theme(panel.grid.minor = element_blank(),
        axis.text.x = element_text(angle = 0))

ggplotly(p_pobreza_tasa, tooltip = c("x", "y")) |>
  layout(paper_bgcolor = FONDO_APP, plot_bgcolor = "#FFFFFF") |>
  centrar_grafico()

Diagnóstico del gráfico — Figura 6

Tipo de gráfico: gráfico de área con línea y puntos (serie de tiempo anual).

¿Por qué este tipo de gráfico? El área sombreada bajo la línea refuerza visualmente la magnitud acumulada del fenómeno (pobreza monetaria) y facilita distinguir este indicador de los gráficos de línea simple usados en otras secciones del informe. Al ser datos anuales (no mensuales), los puntos marcados sobre la línea permiten ubicar con precisión cada observación real, evitando que el lector interprete valores interpolados entre años como datos reales.

Lectura diagnóstica: el área permite apreciar de un vistazo los tres períodos: la fase de reducción sostenida (2012–2019), el salto abrupto durante la pandemia y la posterior fase de recuperación, sin necesidad de comparar valores exactos punto por punto.

6.2 Variación Anual de la Tasa de Pobreza

df_pob_var <- df_pobreza |>
  arrange(Año) |>
  mutate(
    Tasa_pct   = .data[[col_tasa]],
    Variacion  = Tasa_pct - lag(Tasa_pct),
    Color_var  = ifelse(Variacion >= 0, "Aumento", "Reducción")
  ) |>
  filter(!is.na(Variacion))

offset_etiqueta_var <- diff(range(df_pob_var$Variacion, na.rm = TRUE)) * 0.05

p_var_pob <- ggplot(df_pob_var, aes(x = factor(Año), y = Variacion, fill = Color_var)) +
  geom_col(width = 0.65) +
  geom_hline(yintercept = 0, color = TEXTO, linewidth = 0.7) +
  geom_text(aes(y = Variacion + ifelse(Variacion >= 0, offset_etiqueta_var, -offset_etiqueta_var),
                label = paste0(ifelse(Variacion > 0, "+", ""), round(Variacion, 1), " pp")),
            size = 3.3, color = TEXTO) +
  scale_fill_manual(values = c("Aumento" = AZUL_DESTACADOS, "Reducción" = VERDE),
                    name = "") +
  scale_y_continuous(expand = expansion(mult = c(0.15, 0.15))) +
  labs(title    = "Variación Anual de la Tasa de Pobreza",
       subtitle = "Puntos porcentuales (pp) respecto al año anterior",
       x = "Año", y = "Variación (pp)",
       caption = "Fuente: DANE — Informe de Pobreza Monetaria") +
  tema_corporativo +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

ggplotly(p_var_pob, tooltip = c("x", "y", "fill")) |>
  layout(paper_bgcolor = FONDO_APP, plot_bgcolor = "#FFFFFF") |>
  centrar_grafico()

Diagnóstico del gráfico — Figura 7

Tipo de gráfico: barras divergentes (positivas/negativas) con línea base en cero.

¿Por qué este tipo de gráfico? La Figura 6 muestra el nivel de la tasa de pobreza, pero no responde con la misma claridad “¿en qué años empeoró o mejoró la situación, y en cuánto?”. Las barras divergentes están diseñadas específicamente para variables de cambio o variación (aumento vs. reducción): al anclarse en una línea base de cero, la dirección de la barra (hacia arriba o hacia abajo) codifica el signo del cambio, y el color refuerza esa lectura sin ambigüedad.

Lectura diagnóstica: las barras verdes (reducción) predominan en los años de recuperación económica, mientras que la barra azul de mayor tamaño identifica inmediatamente el año de mayor deterioro (el salto pandémico), permitiendo cuantificar el retroceso en puntos porcentuales de un solo vistazo.

6.3 Tabla de Datos — Pobreza Monetaria

df_pobreza |>
  mutate(
    Tasa_fmt     = paste0(round(.data[[col_tasa]], 1), "%"),
    Personas_fmt = scales::comma(round(.data[[col_personas]], 0))
  ) |>
  select(Año, Tasa_fmt, Personas_fmt) |>
  setNames(c("Año", "Tasa de Pobreza (%)", "Personas en Pobreza (miles)")) |>
  knitr::kable(caption = "Tabla 3. Indicadores de Pobreza Monetaria en Colombia.",
               align = c("c", "c", "r"))
Tabla 3. Indicadores de Pobreza Monetaria en Colombia.
Año Tasa de Pobreza (%) Personas en Pobreza (miles)
2012 41% 17,938
2013 38.7% 17,086
2014 37% 16,465
2015 36.8% 16,526
2016 36.8% 16,712
2017 35.9% 16,500
2018 35.5% 16,644
2019 36.5% 17,461
2020 43.1% 21,059
2021 39.7% 19,634
2022 36.6% 18,332
2023 34.6% 17,505
2024 31.8% 16,238
2025 28% 14,447

6.4 Interpretación

Hallazgos principales sobre pobreza monetaria:

  • Colombia logró reducir la pobreza monetaria del 41% en 2012 al 36.5% en 2019, producto del crecimiento económico y la expansión de los programas sociales.

  • El año 2020 (COVID-19) representó el mayor retroceso en la reducción de la pobreza del período analizado, alcanzando una tasa de 43.1%, con un incremento significativo tanto en la tasa como en el número de personas afectadas.

  • La recuperación posterior incluyó la mayor reducción anual registrada en 2025 (-3.8 pp), impulsada por la reactivación económica y los subsidios gubernamentales.

  • Al 2025, la tasa se sitúa en 28% (mínimo histórico del período: 28% en 2025). Persiste un núcleo de pobreza estructural que subraya la necesidad de políticas focalizadas más allá del crecimiento del PIB.


7 Caracterización por Género

7.1 Comparación de TGP, TO y TD por Género

anio_genero_max <- max(df_gen_anual$Año)

df_gen_ref <- df_gen_anual |>
  filter(Año == anio_genero_max)

# Detectar los valores reales de sexo en los datos
sexos_unicos <- unique(df_gen_ref$`SEXO + TOTAL`)
es_femenino <- function(x) grepl("FEM|MUJ|fem|muj|F$|mujer", x, ignore.case = TRUE)
color_sexo <- ifelse(es_femenino(sexos_unicos), AZUL_DESTACADOS, AZUL_PRINCIPAL)
names(color_sexo) <- sexos_unicos

label_sexo <- ifelse(es_femenino(sexos_unicos), "Mujer", "Hombre")
names(label_sexo) <- sexos_unicos

offset_etiqueta_gen <- max(df_gen_ref$Valor, na.rm = TRUE) * 0.06

p_gen_barras <- ggplot(df_gen_ref,
                        aes(x = Indicador, y = Valor,
                            fill = `SEXO + TOTAL`)) +
  geom_col(position = position_dodge(0.75), width = 0.65) +
  geom_text(aes(y = Valor + offset_etiqueta_gen,
                label = paste0(round(Valor, 1), "%")),
            position = position_dodge(0.75),
            size = 3.5, color = TEXTO) +
  scale_fill_manual(values = color_sexo, name = "Género",
                    labels = label_sexo) +
  scale_y_continuous(labels = scales::label_percent(scale = 1, suffix = "%"),
                     expand = expansion(mult = c(0, 0.18))) +
  labs(title    = paste0("Brechas de Género en el Mercado Laboral — ", anio_genero_max),
       subtitle = "Tasa Global de Participación (TGP), Tasa de Ocupación (TO), Tasa de Desocupación (TD)",
       x = "Indicador", y = "(%)",
       caption = "Fuente: DANE — GEIH") +
  tema_corporativo

ggplotly(p_gen_barras, tooltip = c("x", "y", "fill")) |>
  layout(paper_bgcolor = FONDO_APP, plot_bgcolor = "#FFFFFF",
         barmode = "group",
         legend = list(orientation = "h", x = 0.3, y = -0.2)) |>
  centrar_grafico()

Diagnóstico del gráfico — Figura 8

Tipo de gráfico: barras agrupadas (comparación categórica cruzada: indicador × género).

¿Por qué este tipo de gráfico? Se busca comparar tres indicadores (TGP, TO, TD) entre dos grupos (hombres/mujeres) en un único año. Las barras agrupadas son el estándar para este tipo de comparación de dos factores categóricos, ya que permiten leer tanto la diferencia entre géneros dentro de cada indicador (comparando barras adyacentes) como la relación entre los tres indicadores dentro de un mismo género.

Lectura diagnóstica: la brecha visual entre cada par de barras (hombre/mujer) cuantifica directamente la desigualdad de género en cada indicador; la comparación entre pares permite identificar en cuál de los tres indicadores la brecha es proporcionalmente mayor.

7.2 Evolución Histórica de la Brecha de Género

df_brecha <- df_gen_anual |>
  pivot_wider(names_from = `SEXO + TOTAL`,
              values_from = Valor,
              names_prefix = "Sexo_") |>
  # Detectar columnas de sexo generadas por pivot_wider
  (\(d) {
    cols_sexo <- setdiff(names(d), c("Año", "Indicador"))
    col_masc  <- cols_sexo[!grepl("FEM|MUJ|fem|muj", cols_sexo, ignore.case = TRUE)][1]
    col_fem   <- cols_sexo[ grepl("FEM|MUJ|fem|muj", cols_sexo, ignore.case = TRUE)][1]
    d |> mutate(Brecha = .data[[col_masc]] - .data[[col_fem]])
  })() |>
  filter(!is.na(Brecha))

p_brecha <- ggplot(df_brecha, aes(x = Año, y = Brecha,
                                   color = Indicador, group = Indicador)) +
  geom_hline(yintercept = 0, color = "#9CA3AF", linewidth = 0.8, linetype = "dashed") +
  geom_line(linewidth = 1.6) +
  geom_point(size = 3, shape = 21, fill = "white", stroke = 1.5) +
  # Nota de legibilidad: los 3 tonos de azul originales eran poco distinguibles
  # entre si. Se usan 3 colores de alto contraste dentro de la paleta corporativa
  # extendida (navy / naranja / verde) para que cada serie se identifique sin
  # depender del tooltip interactivo.
  scale_color_manual(
    values = c(TGP = AZUL_PRINCIPAL, TO = VERDE, TD = NARANJA),
    name = "Indicador"
  ) +
  scale_y_continuous(labels = scales::label_percent(scale = 1, suffix = " pp")) +
  scale_x_continuous(breaks = seq(2010, 2026, by = 2)) +
  labs(title    = "Brecha de Género (Hombre − Mujer)",
       subtitle = "Diferencia en puntos porcentuales — promedio anual",
       x = "Año", y = "Brecha (pp)",
       caption = "Fuente: DANE — GEIH") +
  tema_corporativo

ggplotly(p_brecha, tooltip = c("x", "y", "colour")) |>
  layout(paper_bgcolor = FONDO_APP, plot_bgcolor = "#FFFFFF",
         legend = list(orientation = "h", x = 0.3, y = -0.2)) |>
  centrar_grafico()

Diagnóstico del gráfico — Figura 9

Tipo de gráfico: líneas múltiples con línea de referencia en cero (serie de tiempo de una variable derivada: la brecha).

¿Por qué este tipo de gráfico? La Figura 8 solo muestra un año; para responder si las brechas de género se han reducido o ampliado con el tiempo, se necesita una serie histórica. En lugar de graficar las tasas de hombres y mujeres por separado (lo que obligaría al lector a calcular la diferencia mentalmente), se grafica directamente la brecha ya calculada (hombre − mujer), con una línea horizontal en cero como referencia de “brecha nula”. Esto simplifica la lectura y hace evidente si la desigualdad aumenta, disminuye o se revierte.

Lectura diagnóstica: una línea que se acerca a cero indica reducción de la brecha; si TD se ubica en valores negativos, significa que la desocupación femenina supera a la masculina; el cruce eventual de una serie por la línea de cero marcaría un cambio de signo en la desigualdad de ese indicador.

7.3 Evolución de la TO y TD por Género

# CORRECCIÓN: estos 4 objetos (df_gen_evol, etiquetas_indicador, color_sexo_evol,
# label_sexo_evol) se usaban mas abajo pero nunca se habian creado, lo que
# impedía que este gráfico se generara. Se construyen aquí a partir de
# df_gen_anual y reutilizando color_sexo / label_sexo ya calculados en el
# chunk de la Figura 8.
df_gen_evol <- df_gen_anual |>
  filter(Indicador %in% c("TO", "TD"))

etiquetas_indicador <- c(
  TO = "Tasa de Ocupación (TO)",
  TD = "Tasa de Desocupación (TD)"
)

color_sexo_evol <- color_sexo
label_sexo_evol <- label_sexo

p_gen_evol <- ggplot(df_gen_evol,
                      aes(x = Año, y = Valor, color = `SEXO + TOTAL`,
                          group = `SEXO + TOTAL`)) +
  geom_line(linewidth = 1.1) +
  geom_point(size = 1.8) +
  facet_wrap(~ Indicador, ncol = 1, scales = "free_y",
             labeller = labeller(Indicador = etiquetas_indicador)) +
  scale_color_manual(values = color_sexo_evol, name = "Género",
                      labels = label_sexo_evol) +
  scale_x_continuous(breaks = scales::pretty_breaks(n = 8)) +
  scale_y_continuous(labels = scales::label_percent(scale = 1, suffix = "%"),
                      expand = expansion(mult = c(0.08, 0.12))) +
  labs(title    = "Evolución de la Tasa de Ocupación y Desocupación por Género",
       subtitle = paste0("Colombia, ", min(df_gen_evol$Año), "–", max(df_gen_evol$Año)),
       x = NULL, y = "(%)",
       caption = "Fuente: DANE — GEIH") +
  tema_corporativo +
  theme(strip.background = element_rect(fill = AZUL_PRINCIPAL),
        strip.text = element_text(color = "#FFFFFF", face = "bold",
                                   margin = margin(t = 6, b = 6)),
        panel.spacing.y = unit(1.4, "lines"),
        legend.position = "bottom")

ggplotly(p_gen_evol, tooltip = c("x", "y", "colour")) |>
  layout(paper_bgcolor = FONDO_APP, plot_bgcolor = "#FFFFFF",
         legend = list(orientation = "h", x = 0.3, y = -0.15),
         margin = list(t = 60, b = 40)) |>
  centrar_grafico()

Diagnóstico del gráfico — Figura 10

Tipo de gráfico: líneas por género, en paneles separados (facetas) para TO y TD.

¿Por qué este tipo de gráfico? TO y TD se dejan en paneles independientes (en lugar de una sola gráfica con las 4 líneas juntas) porque cada indicador tiene una magnitud y un comportamiento distintos; mezclarlos en un solo eje Y comprimiría las variaciones de uno de los dos y dificultaría ver los detalles de ambas series (scales = "free_y" permite que cada panel use su propia escala). Dentro de cada panel, el color por género permite comparar directamente hombres y mujeres para ese indicador específico.

Lectura diagnóstica: el panel superior (TO) muestra el nivel de empleabilidad de cada género a lo largo del tiempo; el panel inferior (TD) permite observar si la brecha de desempleo entre géneros se mantiene, crece o se cierra en los años más recientes, complementando la lectura agregada (brecha) de la Figura 9 con el detalle de cada serie por separado.

7.4 Interpretación

Hallazgos principales sobre brechas de género (2025):

  • La Tasa Global de Participación (TGP) evidencia la brecha más amplia entre hombres y mujeres: 76.8% (hombres) vs. 52.8% (mujeres) — una diferencia de 24 pp. Los hombres participan activamente en mayor proporción, aunque la brecha ha tendido a reducirse en el período analizado.

  • La Tasa de Desocupación es 11.4% en mujeres vs. 7% en hombres (4.4 pp de diferencia), lo que indica que las mujeres que participan en el mercado laboral enfrentan mayores dificultades para encontrar empleo.

  • El COVID-19 afectó de manera diferencial por género: la Tasa de Desocupación femenina registró un incremento proporcionalmente mayor, producto de la concentración de mujeres en sectores de servicios y trabajo informal.

  • A pesar de los avances, las brechas en TGP y TO persisten, lo que señala barreras estructurales (trabajo no remunerado del hogar, segregación sectorial, discriminación salarial) que trascienden la dinámica macroeconómica.


8 Correlación entre Salario Mínimo y Fuerza de Trabajo

8.1 Análisis de Correlación

modelo_lm   <- lm(FuerzaTrabajo ~ SalarioMinimo, data = df_smlv)
r_cuadrado  <- round(summary(modelo_lm)$r.squared, 4)
pearson_r   <- round(cor(df_smlv$SalarioMinimo, df_smlv$FuerzaTrabajo,
                          method = "pearson"), 4)
spearman_r  <- round(cor(df_smlv$SalarioMinimo, df_smlv$FuerzaTrabajo,
                          method = "spearman"), 4)
pendiente   <- round(coef(modelo_lm)[2], 6)
intercepto  <- round(coef(modelo_lm)[1], 2)
0.9647
Correlación de Pearson (r)
0.9882
Correlación de Spearman (ρ)
0.9307
Coeficiente de determinación (R²)
93.1%
Varianza explicada

8.2 Ecuación de Regresión y Residuos

df_smlv_resid <- df_smlv |>
  mutate(
    Predicho  = predict(modelo_lm),
    Residuo   = FuerzaTrabajo - Predicho,
    Color_res = ifelse(Residuo >= 0, "Positivo", "Negativo")
  )

# Determinar unidad de los residuos según escala de FuerzaTrabajo
max_ft <- max(abs(df_smlv$FuerzaTrabajo), na.rm = TRUE)
unidad_resid <- if (max_ft > 1e6) "personas" else if (max_ft > 1e3) "miles de personas" else "unidades"

p_resid <- ggplot(df_smlv_resid, aes(x = factor(AÑOS), y = Residuo,
                                      fill = Color_res)) +
  geom_col(width = 0.7) +
  geom_hline(yintercept = 0, color = TEXTO, linewidth = 0.8) +
  geom_text(aes(label = scales::comma(round(Residuo, 0)),
                vjust = ifelse(Residuo >= 0, -0.4, 1.3)),
            size = 2.9, color = TEXTO) +
  scale_fill_manual(values = c(Positivo = AZUL_DESTACADOS, Negativo = NARANJA),
                    name = "Residuo") +
  labs(title    = "Residuos del Modelo de Regresión Lineal",
       subtitle = paste0("Ŷ = ", scales::comma(round(intercepto, 0)),
                         " + ", round(pendiente * 1000, 4),
                         " × SMLV (miles de COP)"),
       x = "Año", y = paste0("Residuo (", unidad_resid, ")"),
       caption = "Fuente: elaboración propia con datos DANE") +
  tema_corporativo +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

ggplotly(p_resid, tooltip = c("x", "y", "fill")) |>
  layout(paper_bgcolor = FONDO_APP, plot_bgcolor = "#FFFFFF") |>
  centrar_grafico()

Diagnóstico del gráfico — Figura 11

Tipo de gráfico: barras de residuos con línea base en cero (diagnóstico de modelo de regresión).

¿Por qué este tipo de gráfico? Este gráfico no describe los datos originales sino la calidad del ajuste del modelo de regresión (SMLV vs. Fuerza de Trabajo, calculado más arriba): el residuo es la diferencia entre el valor observado y el valor predicho por la regresión. Las barras divergentes (positivas/negativas respecto a cero) son el estándar en diagnóstico de regresión porque permiten detectar de inmediato patrones no aleatorios en los errores (por ejemplo, residuos que crecen con el tiempo), lo cual indicaría que el modelo lineal no captura toda la relación.

Lectura diagnóstica: si los residuos se distribuyen sin un patrón sistemático alrededor de cero, el ajuste lineal es razonable; si se observan agrupaciones de residuos del mismo signo en años consecutivos (por ejemplo, alrededor de 2020), esto sugiere que un choque externo (la pandemia) no fue capturado por el modelo y que la relación SMLV–Fuerza de Trabajo podría no ser puramente lineal en todo el período.

9 Conclusiones

Con base en el análisis de los cinco módulos desarrollados, se sintetizan las siguientes conclusiones:

1. Mercado Laboral Nacional: Colombia registró avances en la reducción del desempleo durante la última década. La Tasa de Desocupación pasó de 12% en 2010 a 8.9% en 2025, con el pico pandémico de 16.7% en 2020. La recuperación post-COVID ha sido parcial, y persisten niveles de informalidad y subempleo.

2. Heterogeneidad Territorial: Las diferencias entre ciudades son sustanciales (17.3 pp de brecha entre Quibdó y Bucaramanga), lo que demanda políticas diferenciadas por región que atiendan las particularidades productivas y demográficas de cada área metropolitana.

3. Pobreza Monetaria: La tendencia decreciente (41% en 2012 → 36.5% en 2019) fue interrumpida por la pandemia, que elevó la tasa al 43.1% en 2020. Al 2025 la tasa se recuperó a 28%, aunque persiste un núcleo de pobreza estructural.

4. Brechas de Género: En 2025, la TGP masculina supera a la femenina en 24 pp, y la TD femenina supera a la masculina en 4.4 pp. Las brechas se han reducido lentamente, pero su persistencia señala barreras sistémicas. que requieren intervención específica.

5. SMLV y Fuerza Laboral: La correlación de Pearson (r = 0.9647, R² = 0.9307) entre el SMLV y la Fuerza de Trabajo refuerza la importancia del salario mínimo como mecanismo de inclusión económica, aunque su efecto debe analizarse en conjunto con el comportamiento demográfico y el ciclo económico.


10 Recomendaciones

A partir de los hallazgos del análisis, se formulan las siguientes recomendaciones de política pública y de investigación:

R1. Fortalecer los sistemas de protección laboral: Diseñar mecanismos anticíclicos que amortigüen el impacto de choques externos sobre el empleo, especialmente en sectores con alta informalidad.

R2. Políticas territoriales diferenciadas: Implementar estrategias de fomento al empleo adaptadas a las realidades de cada ciudad/región, priorizando las que exhiben mayor Tasa de Desocupación estructural.

R3. Programas focalizados de reducción de la pobreza: Complementar el crecimiento económico con transferencias condicionadas y acceso a servicios sociales para el núcleo de pobreza estructural que no se moviliza con el ciclo productivo.

R4. Equidad de género en el mercado laboral: Fortalecer políticas de corresponsabilidad en el cuidado, ampliar el acceso a guarderías, y promover la equidad salarial para reducir las brechas en TGP y TO.

R5. Monitoreo continuo de la relación SMLV–empleo: Profundizar el análisis econométrico de la relación entre salario mínimo, informalidad y empleo, incorporando controles por inflación, productividad y composición sectorial.

R6. Ampliar la desagregación de los datos: Incorporar en análisis futuros las dimensiones étnica, etaria y por nivel educativo, que permitan identificar poblaciones en situación de mayor vulnerabilidad socioeconómica.



Análisis de Evolución Socioeconómica en Colombia
Informe generado con R Markdown — SENA
Datos: DANE – Gran Encuesta Integrada de Hogares (GEIH)
03 de julio de 2026