Análisis de microdatos GEIH del DANE — Colombia. 70+ indicadores: TD, TGP, TO, Gini, Mincer, ICE, ICI, brecha de género, 33 departamentos, informalidad, análisis de tierras y precisión muestral.
Project description
geih-analisis
Paquete Python para analizar los microdatos de la Gran Encuesta Integrada de Hogares (GEIH) del DANE — Colombia.
Convierte los archivos .zip crudos del DANE en indicadores del mercado laboral listos para reportar: desempleo, salarios, brecha de género, formalidad, educación, tenencia de tierra y más — con pocas líneas de código.
English summary: Python package for Colombia's GEIH household survey microdata (DANE). Reads DANE ZIPs directly into RAM, builds a 5M-row Data Lake, and computes labor indicators (unemployment, wages, gender gap, formality, regional CIIU × department).
pip install geih-analisis→from geih import ConfigGEIH.
Tabla de contenidos
- ¿Para quién es este paquete?
- Novedades en la v0.1.5
- Instalación
- Paso 0 — Descargar los datos del DANE
- Inicio rápido
- Flujo de trabajo completo
- Análisis disponibles
- Ejemplos de análisis
- Análisis departamental × rama CIIU
- Análisis por 32 ciudades y áreas metropolitanas
- Análisis de tierras agropecuarias
- Configuración externa y precisión muestral
- Herramientas auxiliares
- Verificación contra el Boletín DANE (NUEVO v0.1.5)
- Desestacionalización de series mensuales (NUEVO v0.1.5)
- Notebooks de replicación y validación
- FAQ
- Cómo citar
- Licencia y metodología
1. ¿Para quién es este paquete?
Este paquete es para ti si:
- Eres economista, analista laboral o investigador y necesitas calcular tasas de desempleo, ingresos medianos o brechas salariales a partir de la GEIH.
- Eres estudiante de pregrado o posgrado y quieres explorar el mercado laboral colombiano sin procesar manualmente millones de filas.
- Trabajas en gobiernos regionales y necesitas indicadores departamentales con evaluación de confiabilidad estadística.
- Investigas política pública agraria y quieres cruzar ingresos con tenencia de tierra.
- Usas Google Colab o Python local y no quieres perder tiempo descomprimiendo archivos.
No necesitas: experiencia avanzada en programación, conocer la estructura interna de la GEIH, ni saber qué es un factor de expansión. El paquete maneja todo eso por ti.
2. Novedades en la v0.1.5
Esta versión está orientada a rigor de validación contra el Boletín DANE. Durante la replicación verbatim del Boletín GEIH Diciembre 2025 con tolerancia ±0.05 p.p., se identificaron seis bugs latentes que producían cifras silenciosamente incorrectas en clasificaciones geográficas y de informalidad. Todos están corregidos, blindados con tests "canario" y documentados.
🛡️ Correcciones críticas
DOMINIOahora se calcula bien. Antes el filtrodf['DOMINIO']=='13_AM'devolvía 0 filas porque la clasificación usabaAREA_A_CIUDAD.keys()(DIVIPOLA de 5 dígitos) en vez deDPTOS_13_CIUDADES(códigos AREA de 2 dígitos del microdato). Ahora produce 4 categorías mutuamente excluyentes que cuadran con el Boletín al primer mil:13_AM,10_ciudades,otras_cab,rural.POSICION_OCUcon código CISE-93 correcto. El mapa anterior tenía cruzados los códigos 7 y 8: jornalero quedaba como código 8 (orden alfabético del cuestionario) en vez del 7 oficial CISE-93 que usan los microdatos publicados. Cifra de control: jornaleros Dic-2025 ≈ 849 mil — ahora cuadra exacto.INFORMALcon definición oficial 17ª CIET. Ahora incorporaP6870(tamaño establecimiento) en la regla de patrones, eliminando el sesgo de +1 a +3 p.p. en zonas rurales.ConfigGEIHya no rechaza meses no contiguos.ConfigGEIH(meses_rango=[12]),[10,11,12]y cualquier subconjunto del calendario funcionan. Antes la validación comparaba el rango contra su propio tamaño y siempre fallaba.PreparadorGEIH.preparar_basederiva variables automáticamente. Antes había que recordar llamaragregar_variables_derivadasmanualmente; ahora es automático con el parámetroderivar=Truepor defecto.
⚙️ Nuevas funcionalidades
IndicadoresLaborales.calcular()exponeTD_raw,TGP_raw,TO_rawsin redondear. Necesario para validar contra el anexo Excel del DANE (precisión 4 decimales) cuando el round a 1 decimal del display destruiría la resolución.- Módulo
geih.estacionalcondesestacionalizar()(STL por defecto, X-13 opcional). Permite replicar la pág. 25 del Boletín DANE — TD desestacionalizada mensual. P6870añadida aCOLUMNAS_DEFAULTy nuevo aliasCOLUMNAS_BOLETINpara documentar la intención cuando se replica el boletín.tests/test_canarios_boletin.py— batería de 26 tests "canario" que validan end-to-end la replicación del Boletín. Si cualquier cambio futuro rompe la replicación, el test correspondiente lo detecta con un mensaje que indica exactamente qué bug ha vuelto y dónde mirar.- Notebook
Verificacion_GEIH_2025_vs_Boletin_DANE_v3.ipynb— replicación verbatim del Boletín Dic-2025 contra el anexo Excel oficial, con CSV maestro de 73+ comparaciones y tolerancia estricta ±0.05 p.p. Plantilla reutilizable para validar futuros boletines.
📋 Migración desde 0.1.5
- Reinstale y reinicie el kernel de Colab/Jupyter (Python cachea módulos).
- Si su código llamaba
agregar_variables_derivadasmanualmente, ya no es necesario — pero mantenerlo no rompe nada (el método es idempotente). - Si dependía de
df['DOMINIO']=='13_AM'antes y obtenía cifras anómalas, revise sus reportes — la lógica anterior producía basura silenciosa. - Para informalidad oficial: si su Parquet fue consolidado antes de 0.1.5, considere reconsolidar para que
P6870entre en la base. Sin ella,INFORMALcae a la versión aproximada y avisa con un warning.
👉 Detalle completo en CHANGELOG.md.
2.bis Novedades en la v0.1.5
Esta versión reorganiza el pipeline de ingesta y añade un nuevo módulo analítico clave:
- 📦 Lectura directa de
.zip→ RAM. ElConsolidadorGEIHahora lee los ZIP mensuales del DANE sin descomprimirlos a disco. Ya no es necesario extraer los CSV manualmente ni crear carpetasCSV/. Coloca los ZIP tal como los descargas y listo. - 🗺️ Nueva clase
OcupadosDptoRama(geih.analisis_dpto_rama) — Ocupados promedio anual por Departamento × Rama CIIU (2 o 4 dígitos) con evaluación de CV bajo diseño complejo (Cochran 1977, Kish 1965). - 🏙️
AnalisisOcupadosCiudadrefactorizado — 6 tablas (nacional, agrupación DANE, dominio geográfico, ciudad/AM, granular CIIU×ciudad, CIIU nacional) + exportación Excel multi-hoja. - 🧱 Separación Data Lake / Data Mart.
ConsolidadorGEIHconstruye el universo completo (~515 columnas, ~5M filas).PreparadorGEIHfiltra al Data Mart analítico. Esto permite reutilizar el Parquet consolidado para análisis no previstos. - 🧩
append_mes()— agrega un mes nuevo al Parquet existente sin reconsolidar todo el año.
👉 Cambios completos en CHANGELOG.md.
3. Instalación
Opción A — pip (recomendado)
pip install geih-analisis
Con el dashboard Streamlit opcional:
pip install "geih-analisis[dashboard]"
Opción B — Google Colab desde Google Drive
from google.colab import drive
drive.mount('/content/drive')
!pip install geih-analisis -q
from geih import __version__
print(f"geih v{__version__} listo")
Requisitos
| Dependencia | Versión mínima |
|---|---|
| Python | 3.9+ |
| pandas | 1.5+ |
| numpy | 1.21+ |
| pyarrow | 10.0+ |
| scipy | 1.7+ |
| openpyxl | 3.0+ |
4. Paso 0 — Descargar los datos del DANE
⚠️ Este paquete no incluye los datos. Los microdatos de la GEIH son públicos y gratuitos, pero debes descargarlos del portal oficial del DANE.
4.1 Dónde descargar
Microdatos GEIH (lo único obligatorio para usar el paquete)
Portal oficial: 🔗 https://microdatos.dane.gov.co
- Abrir el portal y buscar
Gran Encuesta Integrada de Hogares. - Seleccionar el año (ej.
GEIH 2025) → "Obtener microdatos". - Descargar el ZIP mensual de cada mes que quieras analizar. El ZIP contiene los 8 módulos CSV que define el DANE (Características generales, Datos del hogar, Fuerza de trabajo, Ocupados, No ocupados, Otras formas de trabajo, Migración, Otros ingresos).
Los archivos
.DATy.SAVson para software estadístico especializado (SPSS, SAS) y no se usan aquí. Solo necesitas el ZIP que contiene los CSV.
Documentación técnica oficial — leerla evita errores graves
| Recurso | Para qué sirve | Dónde |
|---|---|---|
| Manual DDI-853 | Diccionario completo de variables del microdato (P3271=sexo, P6430=posición ocupacional, etc.). Indispensable para entender qué codifica cada columna. |
https://microdatos.dane.gov.co/index.php/catalog/853 |
| Boletín mensual GEIH | Cifras oficiales publicadas. Use siempre el más reciente como fuente-de-verdad cuando valide cálculos propios. Trae el PDF de "Principales resultados" + el anexo Excel con precisión completa. | https://www.dane.gov.co/index.php/estadisticas-por-tema/mercado-laboral/empleo-y-desempleo |
| DIVIPOLA | División Político-Administrativa (códigos de departamento y municipio). Crítica si va a cruzar GEIH con otras fuentes. | https://geoportal.dane.gov.co/servicios/descarga-y-metadatos/datos-geoestadisticos/?cod=112 |
| CIIU Rev. 4 A.C. | Clasificación Industrial Internacional Uniforme adaptada para Colombia. Define qué significa cada código de RAMA2D_R4 y RAMA4D_R4. |
https://www.dane.gov.co/index.php/sistema-estadistico-nacional-sen/normas-y-estandares/nomenclaturas-y-clasificaciones/clasificaciones/clasificacion-industrial-internacional-uniforme-de-todas-las-actividades-economicas-ciiu |
| Tablas correlativas | Conversiones entre clasificaciones (CIIU↔CPC, CIIU↔CIUO). Útiles si va a cruzar con Censo Económico, EAM, EAS. | https://www.dane.gov.co/index.php/sistema-estadistico-nacional-sen/normas-y-estandares/nomenclaturas-y-clasificaciones/tablas-correlativas |
| Nota metodológica de Informalidad | Definición operativa de la 17ª CIET aplicada por el DANE. Lectura recomendada antes de interpretar la columna INFORMAL. |
https://www.dane.gov.co/files/investigaciones/boletines/ech/ech/Nueva_medicion_informalidad.pdf |
🛑 Regla de oro: cualquier indicador que produzca con esta librería debe validarse contra el boletín DANE más reciente antes de publicarse o enviarse a un tomador de decisiones. La librería es una herramienta de cálculo, no una fuente oficial. Si una cifra suya difiere del boletín en más de la tolerancia que tenga el indicador (típicamente ±0.05 p.p. para tasas, ±1 mil para poblaciones), algo está mal en su consolidado o en su código — no en el boletín. Use el notebook de verificación de la sección 13 como plantilla de validación.
4.2 Organización de los archivos — carpeta data/
A partir de la v0.1.5 la estructura es radicalmente más simple. Crea una carpeta data/ (o como prefieras) y coloca los ZIP tal como los descargaste, renombrándolos con el patrón <Mes> <Año>.zip:
data/ ← tu variable RUTA
│
├── Enero 2025.zip ← ZIP descargado del DANE, sin extraer
├── Febrero 2025.zip
├── Marzo 2025.zip
├── Abril 2025.zip
├── Mayo 2025.zip
├── Junio 2025.zip
├── Julio 2025.zip
├── Agosto 2025.zip
├── Septiembre 2025.zip
├── Octubre 2025.zip
├── Noviembre 2025.zip
└── Diciembre 2025.zip
Nombres exactos:
Enero 2025.zip,Febrero 2025.zip, …Diciembre 2025.zip. Mayúscula inicial, espacio, año, extensión.zip. Esta es la nomenclatura que el paquete busca.Compatibilidad hacia atrás: si ya tienes los CSV extraídos en carpetas
Enero 2025/CSV/..., el paquete sigue reconociéndolas como fallback. Pero para nuevos usuarios, lo recomendado es dejar los ZIP tal cual.
4.3 Verificar que todo está en orden
from geih import ConsolidadorGEIH, ConfigGEIH
config = ConfigGEIH(anio=2025, n_meses=12)
cons = ConsolidadorGEIH(ruta_base='data', config=config)
cons.verificar_estructura()
# ✅ Enero 2025.zip: 8 módulos — OK
# ✅ Febrero 2025.zip: 8 módulos — OK
# ...
Si falta un ZIP, está corrupto, o le falta un módulo adentro, el verificador te lo dice exactamente.
5. Inicio rápido
Ultra-rápido — 3 líneas (si ya consolidaste antes)
from geih import ConfigGEIH, ConsolidadorGEIH, PreparadorGEIH, IndicadoresLaborales
config = ConfigGEIH(anio=2025, n_meses=12)
geih = ConsolidadorGEIH.cargar('data/GEIH_2025_Consolidado.parquet')
df = PreparadorGEIH(config=config).preparar_base(geih)
r = IndicadoresLaborales(config=config).calcular(df)
print(f"TD={r['TD_%']:.1f}% TGP={r['TGP_%']:.1f}% TO={r['TO_%']:.1f}%")
Completo — desde los ZIP hasta los resultados
from geih import (
ConfigGEIH, ConsolidadorGEIH, PreparadorGEIH,
IndicadoresLaborales, AnalisisSalarios, BrechaGenero, Exportador,
)
import os
# 1. Configurar
RUTA = 'data' # carpeta con los ZIP
config = ConfigGEIH(anio=2025, n_meses=12)
config.resumen() # muestra SMMLV, período y ZIP esperados
# 2. Consolidar los ZIP del DANE (primera vez: ~5 min; luego instantáneo)
PARQUET = f'{RUTA}/GEIH_{config.anio}_Consolidado.parquet'
if os.path.exists(PARQUET):
geih = ConsolidadorGEIH.cargar(PARQUET)
else:
cons = ConsolidadorGEIH(ruta_base=RUTA, config=config, incluir_area=True)
cons.verificar_estructura()
geih = cons.consolidar(checkpoint=True) # retoma si Colab se cae
cons.exportar(geih, PARQUET)
# 3. Preparar el Data Mart
prep = PreparadorGEIH(config=config)
df = prep.preparar_base(geih)
df = prep.agregar_variables_derivadas(df)
# 4. Calcular y exportar
ind = IndicadoresLaborales(config=config)
r = ind.calcular(df)
ind.sanity_check(r, f"Anual {config.anio}") # valida contra cifras DANE
exp = Exportador(ruta_base=RUTA, config=config)
exp.guardar_tabla(ind.por_departamento(df), f'desempleo_dptos_{config.anio}')
print(f"✅ TD={r['TD_%']:.1f}% TGP={r['TGP_%']:.1f}% TO={r['TO_%']:.1f}%")
6. Flujo de trabajo completo
ZIP mensuales del DANE (data/Enero 2025.zip, Febrero 2025.zip, ...)
↓
ConsolidadorGEIH → lee los ZIP a RAM, hace LEFT JOIN de los 8 módulos
↓ sobre el módulo ancla "Características generales".
↓ Guarda GEIH_2025_Consolidado.parquet (Data Lake, ~515 col)
PreparadorGEIH → filtra columnas analíticas (Data Mart),
↓ calcula FEX_ADJ, mapea ramas y departamentos,
↓ agrega variables derivadas (INGLABO_SML, MES_NUM, etc.)
Clases de análisis → TD, salarios, brecha, Gini, ICE, ICI, ITAT,
↓ OcupadosDptoRama, AnalisisOcupadosCiudad, ...
Exportador → resultados_geih_2025/
├── graficas/ (PNG)
├── tablas/ (CSV)
└── excel/ (XLSX multi-hoja)
El único parámetro que cambia: ConfigGEIH
ConfigGEIH(anio=2025, n_meses=12) # año completo
ConfigGEIH(anio=2026, n_meses=3) # primer trimestre
ConfigGEIH(anio=2026, n_meses=1) # solo enero
ConfigGEIH(anio=2025, n_meses=12, meses_rango=[1,2,3,4,5,6]) # primer semestre
ConfigGEIH selecciona automáticamente el SMMLV del año, genera la lista de ZIP esperados y controla cómo se calcula el factor de expansión ajustado.
7. Análisis disponibles
Indicadores fundamentales
| Clase | Qué produce |
|---|---|
IndicadoresLaborales |
TD, TGP, TO — nacional y por departamento |
DistribucionIngresos |
Distribución de ingresos por rangos de SMMLV |
AnalisisSalarios |
Mediana, media, percentiles por rama y edad |
BrechaGenero |
Diferencia salarial H/M por nivel educativo |
IndicesCompuestos |
Coeficiente de Gini del ingreso laboral |
AnalisisRamaSexo |
Composición del empleo por industria y sexo |
Índices compuestos y análisis avanzado
| Clase | Qué produce |
|---|---|
CalidadEmpleo (ICE) |
Pensión + salud + horas + salario |
CompetitividadLaboral (ICI) |
Competitividad laboral por departamento |
VulnerabilidadLaboral (IVI) |
Vulnerabilidad por rama |
MapaTalento (ITAT) |
Oferta, costo y calidad por departamento |
FormalidadSectorial (ICF) |
Formalidad por sector económico |
EcuacionMincer |
Retorno salarial por año de educación |
Estacionalidad |
Variación mensual de TD, TGP, TO |
FuerzaLaboralJoven |
Indicadores para jóvenes 15–28 |
CostoLaboral |
Costo total incluyendo prestaciones (~54%) |
Poblaciones especiales
AnalisisCampesino, AnalisisDiscapacidad (Washington ONU), AnalisisMigracion, AnalisisSobrecalificacion, AnalisisContractual, AnalisisAutonomia, DuracionDesempleo, DashboardSectoresProColombia.
Nuevos / refactorizados en v0.1.5
| Clase | Módulo | Qué produce |
|---|---|---|
OcupadosDptoRama |
geih.analisis_dpto_rama |
Ocupados promedio anual por Departamento × Rama CIIU (2 o 4 dígitos) con CV, IC 95% y clasificación DANE |
AnalisisOcupadosCiudad |
geih.analisis_area |
6 tablas CIIU × 32 ciudades/AM + Excel multi-hoja |
AnalisisDepartamental |
geih.analisis_dpto |
Reporte integral por departamento con precisión muestral |
AnalisisTierraAgropecuario |
geih.analisis_tierra |
Distribución salarial × tenencia de tierra (P3064) |
Otras clases disponibles en el paquete (no listadas arriba)
| Clase | Qué produce |
|---|---|
DiagnosticoCalidad |
Valores faltantes, ceros sospechosos, tipos incorrectos y columnas duplicadas sobre la base consolidada |
Top20Sectores |
Ranking de las 20 ramas CIIU con mayor ocupación |
AnalisisHoras, AnalisisSubempleo |
Horas trabajadas y subempleo subjetivo/objetivo |
AnalisisFFT |
Fuerza de trabajo potencial (extendida) |
AnalisisUrbanoRural |
Brecha cabecera vs resto |
ProductividadTamano |
Productividad aproximada por tamaño de empresa |
ContribucionSectorial |
Aporte de cada sector al empleo total |
AnatomaSalario, FormaPago |
Descomposición del salario y forma de pago (efectivo, transferencia, especie) |
CanalEmpleo |
Cómo consiguieron el empleo los ocupados |
EtnicoRacial, BonoDemografico |
Composición étnica y ventana demográfica |
ProxyBilinguismo |
Proxy de bilingüismo vía P3041 |
AnalisisOtrasFormas, AnalisisOtrosIngresos |
Módulos DANE "Otras formas de trabajo" y "Otros ingresos" |
AnalisisAlcanceMercado, AnalisisDesanimados |
Alcance geográfico de la empresa y trabajadores desanimados |
MergeCorrelativas |
Enriquece el DataFrame con descripciones CIIU Rev.4 y DIVIPOLA legibles |
Comparación entre años
from geih import ComparadorMultiAnio, ConfigGEIH
comp = ComparadorMultiAnio()
comp.agregar_anio(2025, 'data/GEIH_2025_M01.parquet', ConfigGEIH(anio=2025, n_meses=1))
comp.agregar_anio(2026, 'data/GEIH_2026_M01.parquet', ConfigGEIH(anio=2026, n_meses=1))
comp.comparar_indicadores() # TD / TGP / TO con variación anual
comp.comparar_departamentos() # TD por departamento × año
comp.comparar_brecha_genero() # brecha H/M por año
8. Ejemplos de análisis
Tasa de desempleo nacional y por departamento
from geih import IndicadoresLaborales
ind = IndicadoresLaborales(config=config)
r = ind.calcular(df)
print(f"TD={r['TD_%']:.1f}% TGP={r['TGP_%']:.1f}% TO={r['TO_%']:.1f}%")
# → TD=9.8% TGP=63.4% TO=57.2%
td_dpto = ind.por_departamento(df)
print(td_dpto[['Departamento', 'TD_%', 'Ocupados_M']].head(10).to_string(index=False))
Salarios por nivel educativo
from geih.utils import EstadisticasPonderadas as EP
niveles = {10: 'Universitaria', 11: 'Especialización', 12: 'Maestría', 13: 'Doctorado'}
df_edu = df[(df['OCI'] == 1) & (df['INGLABO'] > 0)].copy()
df_edu['NIVEL'] = df_edu['P3042'].map(niveles)
for nivel in niveles.values():
m = df_edu['NIVEL'] == nivel
med = EP.mediana(df_edu.loc[m, 'INGLABO'], df_edu.loc[m, 'FEX_ADJ'])
print(f"{nivel:20s}: ${med:>12,.0f} ({med/config.smmlv:.1f}× SMMLV)")
Brecha salarial de género
from geih import BrechaGenero
print(BrechaGenero().calcular(df))
# Hombres Mujeres Brecha_%
# Media 1.35 1.18 -12.6
# Universitaria 2.10 1.95 -7.1
# Maestría 4.82 4.41 -8.5
9. Análisis departamental × rama CIIU
Replica la metodología oficial del DANE para estimar ocupados por Departamento (DIVIPOLA) y Rama CIIU Rev. 4 adaptada (2 dígitos: 88 divisiones, o 4 dígitos: ~500 clases).
from geih import OcupadosDptoRama, ConfigGEIH
config = ConfigGEIH(anio=2025, n_meses=12)
odr = OcupadosDptoRama(config=config)
tabla_2d = odr.calcular(df, nivel="2d") # 88 divisiones
tabla_4d = odr.calcular(df, nivel="4d") # ~500 clases
odr.exportar_excel(tabla_2d, "ocupados_dpto_rama_2d_2025.xlsx")
Metodología: para cada mes y celda (DPTO, rama), se calcula el total expandido T_m = Σ FEX_C18 y el conteo muestral n_m. El promedio anual es la media de los 12 totales mensuales reponderada por meses con dato. El CV se estima con la fórmula de varianza bajo diseño complejo:
Var(p̂) ≈ DEFF × p(1−p) / n_base
donde n_base es el tamaño muestral del departamento (no de la celda), porque todos los registros del dominio contribuyen a estimar la proporción. Cada celda lleva su clasificación DANE (precisión alta / aceptable / baja / no confiable).
10. Análisis por 32 ciudades y áreas metropolitanas
from geih import AnalisisOcupadosCiudad
area = AnalisisOcupadosCiudad(config=config)
tablas = area.calcular(df) # 6 tablas
area.imprimir(tablas)
area.exportar_excel(tablas, "CIIU_Area_2025.xlsx")
Produce 6 tablas: total nacional, agrupación DANE, dominio geográfico, ciudad/AM, granular CIIU×ciudad, y CIIU nacional. Incluye 3 gráficos (barras por agrupación, barras por ciudades, heatmap rama×ciudad) y exportación Excel multi-hoja. Usa la variable AREA (DIVIPOLA de 5 dígitos del módulo Ocupados) para identificar las 13 ciudades principales, las 10 áreas intermedias y 9 adicionales.
11. Análisis de tierras agropecuarias
from geih import AnalisisTierraAgropecuario
tierra = AnalisisTierraAgropecuario(config=config)
reporte = tierra.reporte_completo(df)
tierra.exportar_excel(reporte, "tierras_2025.xlsx")
Explota P3064 (tenencia), P3064S1 (renta estimada) y P3056 (tipo de actividad) para: brecha de ingresos propietario vs no propietario, costo de oportunidad (ingreso laboral vs renta de la tierra), distribución por género, formalidad agropecuaria, CIIU a 4 dígitos (Agricultura/Silvicultura/Pesca), y desagregación departamental con evaluación de confiabilidad en cada celda.
12. Configuración externa y precisión muestral
geih_config.json — actualizar SMMLV sin esperar un release
{
"smmlv_por_anio": { "2027": 1900000 },
"ref_dane": {
"2026": { "td_anual_pct": 9.2, "tgp_anual_pct": 64.0, "to_anual_pct": 58.0 }
},
"muestreo": { "deff_default": 2.5, "cv_preciso_pct": 7.0, "cv_aceptable_pct": 15.0 }
}
Orden de búsqueda: ruta explícita → GEIH_CONFIG_PATH (env) → ./geih_config.json → ~/.geih/geih_config.json.
Evaluar precisión de cualquier estimación
from geih import evaluar_proporcion
p = evaluar_proporcion(proporcion=0.089, n_registros=50_000,
n_expandido=26_000_000, dominio="Nacional")
print(p.resumen())
# Nacional Est=8.90 EE=0.20 CV=2.3% IC=[8.51, 9.29] ✅ Precisión alta
| CV | Clasificación | Uso |
|---|---|---|
| < 7 % | ✅ Precisión alta | Publicable |
| 7–15 % | ⚠️ Precisión aceptable | Usar con precaución |
| 15–20 % | ⚠️⚠️ Precisión baja | Solo referencia |
| > 20 % | ❌ No confiable | No publicar |
AnalisisDepartamental, OcupadosDptoRama y AnalisisTierraAgropecuario integran esta evaluación en cada fila.
12.bis. Herramientas auxiliares
Además de las clases de análisis, el paquete incluye utilidades técnicas para todo el ciclo de vida del dato:
Diagnóstico de calidad de la base
from geih import DiagnosticoCalidad
diag = DiagnosticoCalidad()
tabla = diag.valores_faltantes(geih, titulo="Base consolidada 2025", umbral_pct=1.0)
diag.verificar_tipos(geih) # detecta tipos incorrectos
diag.columnas_duplicadas(geih) # columnas con contenido idéntico o colineal
Reporta valores faltantes y ceros por columna, tipos de dato sospechosos y columnas potencialmente duplicadas sobre el Data Lake antes de pasar al análisis.
Merge con correlativas CIIU y DIVIPOLA
from geih import MergeCorrelativas
merger = MergeCorrelativas()
df = merger.merge_ciiu(df, ruta_ciiu="correlativas/CIIU_Rev4_Col.xlsx",
sheet_name="CIIU 2022")
df = merger.merge_divipola(df, ruta_divipola="correlativas/DIVIPOLA.xlsx")
Agrega las columnas DESCRIPCION_CIIU y el nombre legible del departamento/municipio a partir de archivos Excel externos. Útil para exportar tablas con etiquetas en lugar de códigos.
Módulo muestral completo
Además de evaluar_proporcion() (§12), el módulo geih.muestreo expone:
from geih import evaluar_media, evaluar_total, clasificar_precision
# Media muestral con IC bajo diseño complejo
evaluar_media(media=2_100_000, desv_est=1_450_000,
n_registros=38_000, n_expandido=22_000_000, dominio="Ocupados").resumen()
# Total expandido (ocupados, desocupados, PEA)
evaluar_total(total=24_500_000, n_registros=50_000,
n_expandido=26_000_000, dominio="Ocupados").resumen()
# Clasificación directa a partir de un CV
clasificar_precision(cv_pct=8.3) # → "⚠️ Precisión aceptable"
Todas las rutinas aplican la fórmula de varianza bajo diseño complejo con DEFF configurable (default 2,5 para GEIH).
Logging estructurado
from geih import configurar_logging, get_logger
configurar_logging(nivel="INFO", archivo="logs/geih_2025.log")
log = get_logger("mi_analisis")
log.info("Inicio del pipeline")
El LoggerGEIH centraliza mensajes del consolidador y los análisis en un único archivo reutilizable desde notebooks.
Dashboard Streamlit (opcional)
from geih import ejecutar_dashboard
ejecutar_dashboard(ruta_base="data", puerto=8501)
# 🌐 Dashboard disponible en http://localhost:8501
Lanza la interfaz Streamlit en segundo plano con filtros y gráficos básicos sobre los Parquet consolidados. Requiere pip install "geih-analisis[dashboard]".
Exportador unificado
from geih import Exportador
exp = Exportador(ruta_base="data", config=config)
exp.guardar_tabla(td_dpto, "desempleo_dptos_2025") # CSV + XLSX
exp.guardar_grafico(fig, "td_por_rama") # PNG en graficas/
Crea automáticamente las subcarpetas resultados_geih_<anio>/tablas/, graficas/ y excel/.
13. Verificación contra el Boletín DANE
🆕 Nuevo en v0.1.5. Esta sección documenta el flujo recomendado para validar que sus cálculos reproducen el Boletín DANE oficial dentro de tolerancia estricta.
Por qué es obligatorio validar
La librería implementa cientos de operaciones sobre microdatos complejos. Aunque la suite de tests garantiza que los cálculos son matemáticamente correctos contra cifras hardcoded del boletín, su consolidado puede tener problemas que la librería no puede detectar: meses faltantes, factores de expansión corruptos, columnas renombradas, joins mal hechos en el módulo de consolidación. La única defensa real es validar el resultado final contra el boletín publicado por el DANE para el mismo período.
El flujo de 5 pasos
- Descargue el boletín mensual del DANE para el período que está analizando (PDF + anexo Excel) desde el portal oficial. El anexo Excel es la fuente-de-verdad: el PDF redondea a 1 decimal y no sirve para validación estricta.
- Identifique 5-10 cifras de control del boletín — típicamente: TD nacional, TGP nacional, ocupados totales, ocupados por dominio (13_AM, rural), tasas por sexo. Estas son sus "canarios".
- Calcule las mismas cifras con la librería, usando
IndicadoresLaborales.calcular()con los campos_raw(sin redondear). - Compare con tolerancia estricta — ±0.05 p.p. para tasas, ±1 mil para poblaciones. Cualquier diferencia mayor es señal de problema.
- Si todo cuadra, su consolidado es confiable y los demás indicadores que calcule sobre la misma base heredan esa confianza. Si no cuadra, no avance hasta entender por qué.
Plantilla mínima de verificación
from geih import ConfigGEIH, PreparadorGEIH, IndicadoresLaborales
# Vista de Diciembre 2025
cfg = ConfigGEIH(anio=2025, n_meses=12, meses_rango=[12])
df_dic = PreparadorGEIH(cfg).preparar_base(geih_raw)
r = IndicadoresLaborales().calcular(df_dic)
# Cifras del Boletín DANE Dic-2025 (anexo Excel, no del PDF redondeado)
TOLERANCIA_PP = 0.05
referencias = {
'TD_raw': 8.0,
'TGP_raw': 64.3,
'TO_raw': 59.2,
}
for clave, ref in referencias.items():
diff = abs(r[clave] - ref)
estado = '✅' if diff <= TOLERANCIA_PP else '❌'
print(f'{estado} {clave}: {r[clave]:.4f} (DANE: {ref} Δ={diff:.4f})')
# Sanity check ácido: PET expandido debe estar ~40.9 M en CUALQUIER vista
# Es el "canario" más sensible: detecta divisores FEX mal aplicados.
pet_M = df_dic.loc[df_dic['PET']==1, 'FEX_ADJ'].sum() / 1e6
assert 40.5 < pet_M < 41.3, f'PET = {pet_M:.2f}M fuera de rango — divisor FEX mal'
Tests "canario" automatizados
El paquete incluye tests/test_canarios_boletin.py — 26 tests organizados en 8 clases que validan end-to-end la replicación del Boletín Dic-2025. Si cualquier cambio en su consolidado (o en una versión futura de la librería) rompe una cifra del boletín, el test correspondiente falla con un mensaje que indica exactamente qué métrica difiere y dónde mirar.
# Correr los canarios contra su consolidado
GEIH_TEST_DATA=/ruta/a/su/consolidado/2025 pytest tests/test_canarios_boletin.py -v
Si la variable de entorno no está definida, los tests se skipean limpiamente — no falla la suite por falta de datos. Esto permite incluirlos en CI sin necesidad de subir microdatos al repositorio.
Tolerancias recomendadas
| Tipo de indicador | Tolerancia | Justificación |
|---|---|---|
| Tasas (TD, TGP, TO, informalidad) | ±0.05 p.p. | Mitad del último decimal publicado por DANE |
| Poblaciones (miles) | ±1 mil | Precisión declarada del anexo Excel |
| Ingresos (pesos/mes) | ±500 COP | ~0.05% del SMMLV |
| Informalidad (rural) | ±0.5 p.p. | Definición oficial DANE incluye registro mercantil que la librería no puede replicar sin metadato extra |
14. Desestacionalización de series mensuales
🆕 Nuevo en v0.1.5. El módulo
geih.estacionalpermite reproducir la sección "TD desestacionalizada" del Boletín DANE (página 25), que separa la tendencia de los efectos estacionales en la serie mensual.
Cuándo usarla
La TD cruda mensual tiene patrones estacionales fuertes: pico en enero (fin de contratos navideños), valle en noviembre (alta contratación pre-navideña). Comparar TD(noviembre) con TD(enero) directamente lleva a conclusiones erróneas. La serie desestacionalizada permite ver la tendencia subyacente.
Uso básico
from geih import ConfigGEIH, PreparadorGEIH
from geih.estacional import desestacionalizar_td_mensual
import pandas as pd
# Vista anual completa
cfg = ConfigGEIH(anio=2025, n_meses=12)
df_anu = PreparadorGEIH(cfg).preparar_base(geih_raw)
# STL requiere ≥24 meses → necesitamos histórico del año anterior.
# Lo más simple es usar las cifras del boletín del año previo:
td_2024 = pd.Series(
[12.1, 11.5, 11.3, 10.6, 10.3, 10.3, 10.0, 9.8, 9.1, 8.4, 8.2, 9.1],
index=pd.period_range('2024-01', '2024-12', freq='M').to_timestamp(),
)
resultado = desestacionalizar_td_mensual(
df_anu, anio=2025, incluir_historico=td_2024,
)
print(resultado.tail(3))
# td_cruda td_desest
# 2025-10-01 7.20 7.51
# 2025-11-01 7.00 7.43
# 2025-12-01 8.00 7.62
Limitación importante
El método por defecto es STL (Seasonal-Trend LOESS), que está siempre disponible vía statsmodels. El DANE usa internamente X-13-ARIMA-SEATS con calendario laboral colombiano (días hábiles, Semana Santa, festivos), parámetros que no exponemos en esta librería. Esperar diferencias de ±0.1 a ±0.3 p.p. entre la curva desestacionalizada por la librería y la publicada por el DANE en el boletín. La forma general (tendencia, picos, valles) sí es reproducible.
15. Notebooks de replicación y validación
🆕 Nuevo en v0.1.5. El proyecto incluye notebooks de ejemplo listos para correr en Google Colab, que sirven como plantillas de validación y como referencia ejecutable de las mejores prácticas.
Verificacion_GEIH_2025_vs_Boletin_DANE_v3.ipynb
Notebook de replicación verbatim del Boletín GEIH Diciembre 2025 contra el anexo Excel oficial del DANE. 9 secciones (A-I) que cubren:
- A — Diciembre mensual: TD/TGP/TO nacional, brecha por sexo, dominio geográfico, ramas CIIU (las 13), posición ocupacional.
- B — Trimestre Oct-Dic: TD por las 23 ciudades del boletín extendido.
- C — Anual Ene-Dic: totales y brechas por sexo.
- D — Informalidad: 6 desagregaciones contra Boletín pág. 42.
- E — Juventud (15-28): TGP/TO/TD por sexo y período.
- F — Étnico: indígenas, negro/afro, sin grupo étnico.
- G — Ingresos laborales (IML por sexo).
- H — Errores muestrales: documenta el gap conocido de la librería.
- I — Replicación de gráficas: TD mensual cruda + desestacionalizada (pág. 25) y dispersión TGP H/M de 23 ciudades (pág. 29).
Produce un CSV maestro (verificacion_maestra.csv) con 73+ comparaciones individuales contra el boletín, cada una marcada como ✅/⚠️/❌ con su diferencia exacta. Úselo como plantilla para validar futuros boletines: solo cambie las cifras de referencia y el período.
Uso en Colab:
# Celda 1: montar drive e instalar
from google.colab import drive
drive.mount('/content/drive')
!pip install geih-analisis --upgrade
# Celda 2..N: el resto del notebook ya ejecutable
Otros notebooks que vienen en el repositorio
| Notebook | Para qué sirve |
|---|---|
01_consolidacion_anual.ipynb |
Pipeline de consolidación de los 12 ZIP mensuales del DANE a Parquet único. Incluye verificar_estructura() y diagnóstico de calidad. |
02_indicadores_basicos.ipynb |
Cálculo de TD/TGP/TO nacional y por departamento. Es el "Hello World" del paquete. |
03_analisis_dpto_rama.ipynb |
Uso de OcupadosDptoRama para producir el Excel multi-hoja del entregable principal (Departamento × CIIU 2d/4d con CV). |
04_brecha_genero.ipynb |
Brecha salarial controlada por nivel educativo y experiencia. |
Todos los notebooks están en la carpeta
notebooks/del repositorio. Si va a contribuir, siempre añada un notebook de ejemplo que muestre la nueva funcionalidad — es el mejor seguro contra el bit-rot de la documentación.
Recomendación de flujo para usuarios nuevos
- Descargar microdatos GEIH del año más reciente del portal DANE.
- Ejecutar
01_consolidacion_anual.ipynbpara construir el Parquet base. Verificar quecons.verificar_estructura()reporta los 12 meses OK. - Ejecutar
Verificacion_GEIH_2025_vs_Boletin_DANE_v3.ipynb(ajustando el año si necesario). Si llega al final con ≥95% ✅, su consolidado es confiable. - Solo entonces empezar a calcular indicadores nuevos para sus reportes. Validar siempre el resultado contra alguna cifra publicada por el DANE.
16. FAQ
¿Tengo que descomprimir los ZIP del DANE?
No. Desde la v0.1.5 el paquete lee directamente desde .zip a RAM. Coloca los ZIP en data/ con el nombre Enero 2025.zip, etc.
¿Qué pasa si ya tenía la estructura vieja con carpetas CSV/?
Sigue funcionando — el consolidador la reconoce como fallback. Pero los nuevos usuarios deberían usar ZIP directamente.
¿Qué es la GEIH? La Gran Encuesta Integrada de Hogares del DANE. Encuesta mensual con más de 250 000 hogares al año. Es la fuente oficial de las tasas de desempleo y empleo de Colombia.
¿Qué es el SMMLV? El Salario Mínimo Mensual Legal Vigente. El paquete lo usa para expresar ingresos en múltiplos comprensibles (ej. "2,3× SMMLV"). Se fija por decreto cada diciembre.
¿Por qué la primera consolidación tarda ~5 minutos? Está leyendo y uniendo ~96 archivos CSV (8 módulos × 12 meses) con ~5 M filas × ~515 columnas, dentro de los ZIP. El resultado se guarda en Parquet: las siguientes veces carga en segundos.
¿Y si Colab se desconecta?
consolidar(checkpoint=True) guarda el avance mes a mes y retoma automáticamente.
¿Puedo analizar un solo mes?
Sí: ConfigGEIH(anio=2026, n_meses=1). Solo necesitas data/Enero 2026.zip.
¿Puedo agregar un mes nuevo sin reconsolidar?
Sí: ConsolidadorGEIH.append_mes() añade un mes al Parquet existente.
¿Los datos tienen costo? No. Son públicos y gratuitos en microdatos.dane.gov.co sin registro.
¿Funciona con años anteriores (2022–2024)? Sí, desde 2022 (Marco Muestral 2018).
¿Los 33 departamentos están incluidos? Sí, los 32 + Bogotá D.C. Para departamentos pequeños (Amazonía, Orinoquía), el paquete advierte automáticamente cuando la muestra es insuficiente.
¿Hay un dashboard visual?
Sí. ejecutar_dashboard(ruta_base="data") lanza una interfaz Streamlit con filtros y gráficos básicos sobre los Parquet consolidados. Requiere pip install "geih-analisis[dashboard]".
¿Puedo enriquecer los códigos CIIU y DIVIPOLA con descripciones legibles?
Sí, con MergeCorrelativas. Agrega DESCRIPCION_CIIU y los nombres de departamento/municipio a partir de archivos Excel de correlativas (§12.bis).
¿Puedo diagnosticar la calidad de la base antes de analizarla?
Sí, con DiagnosticoCalidad: reporta valores faltantes, ceros sospechosos, tipos incorrectos y columnas duplicadas.
¿Puedo agregar variables sin modificar el paquete?
Sí: prep.preparar_base(geih, columnas_extra=["P6870", "P7310", ...]).
17. Cómo citar
@software{forero2026geih,
author = {Forero Herrera, Néstor Enrique},
title = {geih-analisis: Paquete Python para análisis de microdatos GEIH},
year = {2026},
version = {0.1.5},
url = {https://github.com/enriqueforero/geih-analisis},
note = {Datos fuente: Gran Encuesta Integrada de Hogares — DANE, Colombia}
}
Forero Herrera, N. E. (2026). geih-analisis (v0.1.5) [Software]. https://github.com/enriqueforero/geih-analisis
18. Licencia y metodología
MIT — Néstor Enrique Forero Herrera · Colombia · 2026
Los datos de la GEIH son propiedad del DANE (Departamento Administrativo Nacional de Estadística). Este paquete es una herramienta independiente sin afiliación oficial.
Metodología de desarrollo. La arquitectura, la lógica de negocio y los requerimientos son de autoría humana; el autor asume responsabilidad total del código publicado. Se utilizaron modelos de IA generativa (Claude y Gemini) como asistencia técnica para código boilerplate, optimización y refactorización. Ningún bloque asistido por IA se integró sin revisión crítica y validación funcional.
Agradecimientos. El diseño de esta librería se inspiró en notebooks previos compartidos por colegas, cuyo aporte se reconoce explícitamente:
- Lina María Castro compartió notebooks propios sobre consolidación multi-módulo de la GEIH y sobre análisis por municipios, que sirvieron como referencia metodológica inicial para el
ConsolidadorGEIHy paraAnalisisOcupadosCiudad. Aunque la implementación final reescribió ambos módulos desde cero, el enfoque original de Lina fue el punto de partida conceptual. - Nicolás Rivera extendió el trabajo anterior al incorporar mejoras de programación en los notebooks y validó los cálculos de ocupados por municipio × rama de actividad económica, contrastando cifras contra los boletines oficiales del DANE.
Ambos aportes son anteriores al paquete y se reconocen como contribuciones intelectuales al proyecto.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file geih_analisis-0.1.8.tar.gz.
File metadata
- Download URL: geih_analisis-0.1.8.tar.gz
- Upload date:
- Size: 230.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ebd5dbbd45431f1b6f38b31f11d7f799956fdc2a862e54ae1cd28f608a9b08a4
|
|
| MD5 |
0f4a1176970d6bfcafaac5293a558cc7
|
|
| BLAKE2b-256 |
9179f9290649a8935015bacd04f39e8f502a3bca0e2c21aa5f36e7c14233c4b5
|
Provenance
The following attestation bundles were made for geih_analisis-0.1.8.tar.gz:
Publisher:
release.yml on EnriqueForero/geih-analisis
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
geih_analisis-0.1.8.tar.gz -
Subject digest:
ebd5dbbd45431f1b6f38b31f11d7f799956fdc2a862e54ae1cd28f608a9b08a4 - Sigstore transparency entry: 1338829845
- Sigstore integration time:
-
Permalink:
EnriqueForero/geih-analisis@8ea71bccf7babc162d7447607df5d5f498411025 -
Branch / Tag:
refs/tags/v0.1.8 - Owner: https://github.com/EnriqueForero
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8ea71bccf7babc162d7447607df5d5f498411025 -
Trigger Event:
push
-
Statement type:
File details
Details for the file geih_analisis-0.1.8-py3-none-any.whl.
File metadata
- Download URL: geih_analisis-0.1.8-py3-none-any.whl
- Upload date:
- Size: 194.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c89e04986da7166eb081a40928975290249c805ac69558fbee851184f71f6ebd
|
|
| MD5 |
9c64ccff0cd85f286aaffa42584d250a
|
|
| BLAKE2b-256 |
4197267cd7469af9d5351aa19847a66918086e50ea711be05329f41868cb45d5
|
Provenance
The following attestation bundles were made for geih_analisis-0.1.8-py3-none-any.whl:
Publisher:
release.yml on EnriqueForero/geih-analisis
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
geih_analisis-0.1.8-py3-none-any.whl -
Subject digest:
c89e04986da7166eb081a40928975290249c805ac69558fbee851184f71f6ebd - Sigstore transparency entry: 1338829855
- Sigstore integration time:
-
Permalink:
EnriqueForero/geih-analisis@8ea71bccf7babc162d7447607df5d5f498411025 -
Branch / Tag:
refs/tags/v0.1.8 - Owner: https://github.com/EnriqueForero
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8ea71bccf7babc162d7447607df5d5f498411025 -
Trigger Event:
push
-
Statement type: