Ingresos frente al salario mínimo#

¿Cuántos ocupados ganan el salario mínimo, cuántos menos y cuántos más? La variable armonizada ratio_smlv es el ingreso laboral mensual dividido por el salario mínimo del año (dd.SMLV).

import numpy as np

import dane_data as dd

df = dd.geih.load(2025, variables=["fex", "ocupado", "formal", "ingreso_laboral", "ratio_smlv"])
ocupados = df[(df.ocupado == 1) & df.ingreso_laboral.notna()]
dd.SMLV[2025], len(ocupados)
(1423500, 349830)

La distribución#

El histograma usa el factor de expansión como peso (dividido por 12, porque son doce meses):

fig, ax = plt.subplots(figsize=(10, 4.2))
bins = np.arange(0, 4.01, 0.05)
grupos = [ocupados[ocupados.formal == 0], ocupados[ocupados.formal == 1]]
ax.hist([d["ratio_smlv"].clip(upper=4) for d in grupos], bins=bins, stacked=True,
        weights=[d["fex"] / 12 / 1e3 for d in grupos], color=["#eb6834", "#2a78d6"],
        label=["Informales", "Formales"])
ax.axvline(1, color="0.2", lw=1, ls="--")
ax.set_xlabel("Ingreso laboral mensual, en salarios mínimos (4 = 4 o más)")
ax.set_ylabel("Miles de ocupados")
ax.set_title("Ingreso laboral de los ocupados, 2025")
ax.legend();

La distribución tiene un pico enorme justo en un salario mínimo, sobre todo entre los formales: el mínimo es un piso efectivo para el empleo formal. Entre los informales, la mayor parte gana menos del mínimo.

ocupados = ocupados.assign(rango=pd.cut(ocupados["ratio_smlv"], [-np.inf, 0.95, 1.05, 2, np.inf],
                                        labels=["Menos del mínimo", "Alrededor del mínimo (±5 %)",
                                                "Entre 1 y 2 mínimos", "Más de 2 mínimos"]))
dd.tabla(ocupados, por=["formal", "rango"], estadistico="porcentaje").round(1)
formal rango total n_muestra porcentaje
0 0 Menos del mínimo 9332835.4 143453 71.7
1 0 Alrededor del mínimo (±5 %) 781985.0 13204 6.0
2 0 Entre 1 y 2 mínimos 2381531.0 36352 18.3
3 0 Más de 2 mínimos 518554.0 7376 4.0
4 1 Menos del mínimo 541842.9 8327 5.3
5 1 Alrededor del mínimo (±5 %) 2757305.8 42510 27.2
6 1 Entre 1 y 2 mínimos 4050638.4 59202 39.9
7 1 Más de 2 mínimos 2804692.3 39406 27.6

Año por año#

Para varios años se procesa uno a la vez, cargando solo las variables necesarias: así la memoria no crece con el número de años.

filas = []
for anio in range(2008, 2026):
    d = dd.geih.load(anio, variables=["fex", "ocupado", "ingreso_laboral", "ratio_smlv"])
    d = d[(d.ocupado == 1) & d.ingreso_laboral.notna()]
    w = d["fex"]
    filas.append({
        "anio": anio,
        "menos_del_minimo": 100 * w[d.ratio_smlv < 0.95].sum() / w.sum(),
        "alrededor_del_minimo": 100 * w[d.ratio_smlv.between(0.95, 1.05)].sum() / w.sum(),
    })
cerca = pd.DataFrame(filas)
cerca.round(1)
anio menos_del_minimo alrededor_del_minimo
0 2008 43.0 12.1
1 2009 46.9 14.3
2 2010 45.3 13.3
3 2011 46.7 9.9
4 2012 46.0 8.6
5 2013 44.0 13.9
6 2014 41.2 15.1
7 2015 44.3 11.6
8 2016 43.0 15.0
9 2017 42.3 11.2
10 2018 43.8 17.2
11 2019 43.0 16.4
12 2020 53.6 14.4
13 2021 47.6 16.8
14 2022 43.6 18.4
15 2023 45.9 16.6
16 2024 44.8 16.9
17 2025 42.6 15.3
ax = cerca.plot(x="anio", y=["menos_del_minimo", "alrededor_del_minimo"], marker="o", ms=4,
                label=["Menos del mínimo", "Alrededor del mínimo (±5 %)"])
ax.yaxis.set_major_formatter(mtick.PercentFormatter(decimals=0))
ax.set_xlabel("")
ax.set_title("Ocupados con ingreso, según su ingreso frente al mínimo");

Entre el 41 % y el 48 % de los ocupados con ingreso gana menos de 0,95 salarios mínimos todos los años, salvo 2020 (54 %).