Saltar al contenido

Capítulo 3

Los microdatos por dentro: archivos, llaves y variables

Cómo abrir una base anual de la GEIH, identificar personas, hogares y viviendas, leer cada variable con su tipo correcto y producir el primer total expandido.

Daniel Molina BarriosActualizado el 21 de octubre de 2026

Con el diseño de la muestra y el factor de expansión a la vista, toca abrir el archivo. La meta es concreta: abrir una base anual de la GEIH, saber qué es cada fila, reconocer a qué vivienda y a qué hogar pertenece cada persona, leer las variables con el tipo que les corresponde y terminar con un primer total expandido que coincida con el que publica el DANE. Todo lo que sigue se comprobó sobre las cuatro bases anuales de 2022 a 2025. Cada cifra del texto sale de los archivos agregados que produce el laboratorio del libro o de un bloque de código que se muestra junto con la salida que dio al ejecutarlo.

Es tentador tratar esta parte como un trámite previo al análisis, y es justamente donde se originan muchos de los errores graves en cálculos con la GEIH: una unión de tablas que duplica personas, un código de departamento que no aparece porque perdió su cero, un punto que se cuela como dato, una columna seleccionada por posición que en otro año es otra pregunta. Ninguno de esos errores produce un mensaje de advertencia. Lo que producen son cifras plausibles y equivocadas.

De ANDA a una base anual#

Los microdatos de la GEIH se descargan del Archivo Nacional de Datos (ANDA), el catálogo de microdatos del DANE. La ficha metodológica precisa desde cuándo hay información y en qué forma se entrega.

Concepto DANE

“Se cuenta con la información desde el tercer trimestre de 2001. La información se publica de forma anonimizada en el Archivo Nacional de Datos (ANDA)”.

Fuente: Ficha metodológica GEIH V11, p. 11

Las bases anuales que usa este libro se armaron a partir de archivos mensuales divididos en módulos, cada uno con un grupo de preguntas del formulario. La metodología no describe los archivos de la descarga, pero sí los capítulos del formulario de los que salen esas preguntas: vivienda, datos del hogar, registro de personas, características generales, seguridad social en salud, educación, fuerza de trabajo, ocupados, no ocupados, otras formas de trabajo, otros ingresos e impuestos, micronegocios, fecundidad, migración, formación para el trabajo, trabajo infantil e identificación (Metodología GEIH V11, pp. 8-9). La lista exacta de archivos, sus nombres y su formato pueden variar entre años, y este libro no la verificó año por año; hay que revisarla en el catálogo (ANDA, DANE) del año que se vaya a usar.

Para trabajar un año completo hay que hacer dos operaciones. La primera es pegar, dentro de cada mes, los módulos en una tabla ancha con una fila por persona: los módulos de personas se unen por vivienda, hogar y persona, y los de vivienda y hogar, que no tienen una fila por persona, se replican a cada integrante del hogar. La segunda es apilar los doce meses, admitiendo que una columna exista en unos meses y no en otros. El resultado es lo que en este libro se llama base anual apilada: un archivo por año, con una fila por persona encuestada en un mes.

Las bases que usa el libro se recibieron ya pegadas, y el procedimiento que las construyó no estaba entre los materiales. Para que el paso sea reproducible, el laboratorio incluye scripts/00_construir_base_anual.py, que implementa ese procedimiento. Toma como base, en cada mes, el módulo de personas con más filas y le une los demás con una unión por la izquierda, de modo que nadie desaparece y lo que un módulo no trae queda nulo. Antes de cada unión comprueba que las llaves del módulo sean únicas, porque una llave repetida multiplicaría filas en silencio, y verifica que las columnas repetidas entre módulos, como FEX_C18, coincidan con la base en lugar de usarlas para unir.

Pythongeih-lab/scripts/00_construir_base_anual.py
for nombre in sorted(k for k in modulos if k != nombre_base):
    mod = modulos[nombre]
    llaves = [c for c in LLAVES if c in mod.columns and c in base.columns]
    if "DIRECTORIO" not in llaves:
        raise ValueError(f"{nombre} no comparte DIRECTORIO con la base.")
    if mod.select(llaves).is_duplicated().any():
        raise ValueError(f"{nombre}: llaves {llaves} no únicas; la unión duplicaría filas.")
    repetidas = [c for c in mod.columns if c in base.columns and c not in llaves]
    # ... se verifica que FEX_C18 y las demás repetidas coincidan con la base ...
    nuevas = [c for c in mod.columns if c not in base.columns]
    base = base.join(mod.select(llaves + nuevas), on=llaves, how="left")
Fragmento de pegar_mes(). Probado solo con módulos sintéticos; ver la limitación al final del capítulo.

Hay que decir con claridad el alcance de ese script. Está probado con módulos sintéticos que reproducen las situaciones difíciles (un hogar adicional en la vivienda, una persona sin registro en el módulo de ocupados, texto en Latin-1, un factor que no coincide entre módulos), pero no se ha ejecutado contra los módulos reales de ANDA, que no estaban disponibles en el equipo donde se escribió el libro. Cuando se disponga de ellos, la opción --comparar contrasta la base reconstruida con la existente en filas, columnas y llaves. Mientras eso no ocurra, la base anual del libro se valida por su resultado, como se hace en el resto del capítulo, y no por su procedimiento. El capítulo 10 explica cómo correr el script cuando se tengan los módulos.

Las cuatro bases tienen los doce meses completos. La de 2025 trae 817.550 filas y 514 columnas; la de 2022, 919.459 filas y 534 columnas. El número de filas por mes varía poco en 2025, entre 66.559 y 68.710, pero no en todos los años es así: en 2022 baja de 80.116 en enero a 72.846 en diciembre. En hogares, la base de 2025 suma 292.942 hogares-mes, unos 24.412 por mes en promedio. La metodología espera encuestar en promedio 25.470 hogares al mes (Metodología GEIH V11, p. 17), pero esa es una cifra de diseño y la de la base cuenta encuestas efectivas; el capítulo 2 explica por qué una cifra no se puede deducir de la otra.

Vivienda, hogar y persona en una sola tabla#

La encuesta observa tres tipos de unidades anidadas, que la metodología enumera al definir sus unidades estadísticas.

Concepto DANE

“Unidad de observación: corresponden a las viviendas, los hogares y las personas”.

Fuente: Metodología GEIH V11, p. 14

De esas tres, la frontera entre vivienda y hogar es la que más consecuencias tiene para quien trabaja la base. Para el DANE, el hogar es “una persona o grupo de personas, parientes o no, que: ocupan la totalidad o parte de una unidad de vivienda; atienden necesidades básicas con cargo a un presupuesto común y generalmente comparten las comidas” (Metodología GEIH V11, pp. 30-31). Una vivienda puede albergar más de un hogar, y cuando eso ocurre cada hogar tiene su propio registro de hogar y de personas dentro de la misma vivienda.

La base anual aplana esa jerarquía en una sola tabla. Cada fila es un registro persona-mes, una persona en el mes en que se encuestó su hogar, y lleva repetidos los datos de su hogar y de su vivienda. Es cómodo para calcular, pero esconde la estructura: quien mira la tabla ve filas, no viviendas con hogares adentro. La figura 3.1 devuelve esa estructura con los conteos reales de cada año.

Figura 3.1Vivienda, hogar y persona en las bases anuales, con sus llavesEn 2025, 289.262 de 290.925 viviendas tienen un solo hogar; las 1.663 restantes bastan para que DIRECTORIO + ORDEN repita 3.705 filas.
Ilustración: una vivienda con dos hogares. En cada hogar el ORDEN vuelve a empezar en 1, por eso DIRECTORIO más ORDEN repite combinaciones y hace falta SECUENCIA_P.ViviendaDIRECTORIOHogar 1SECUENCIA_P = 1PersonaORDEN = 1PersonaORDEN = 2PersonaORDEN = 3Hogar 2SECUENCIA_P = 2PersonaORDEN = 1PersonaORDEN = 2

Ilustración. En cada hogar la numeración ORDEN empieza en 1: con DIRECTORIO y ORDEN solos, las dos personas resaltadas tendrían la misma llave.

  1. Vivienda

    DIRECTORIO

    290.925 viviendas en el año

  2. Hogar-mes

    DIRECTORIO + SECUENCIA_P

    292.942 hogares-mes

  3. Persona-mes

    DIRECTORIO + SECUENCIA_P + ORDEN

    817.550 filas (ninguna repetida)

  4. Llave incompleta

    DIRECTORIO + ORDEN

    3.705 filas repiten una combinación ya vista en 2025.

2025: 817.550 filas, 514 columnas y 12 meses. El 99,43 % de las viviendas tiene un solo hogar; en promedio hay 2,79 personas por hogar-mes. Ninguna vivienda aparece en más de un mes del año. Ningún DIRECTORIO de 2025 aparece en la base del año anterior: no hay panel. Todas las personas de una vivienda en un mes tienen el mismo FEX_C18.

Hogares por vivienda en 2025
Número de viviendas según cuántos hogares tienen, 2025
Hogares en la viviendaViviendas%
1289.26299,43
21.3700,47
32460,08
4390,01
530,00
640,00
710,00

Conteos propios sobre las bases anuales de la GEIH (marco 2018), sin factor de expansión. Una fila es una persona en un mes. En 2025 ninguna vivienda se repite entre meses, así que cada hogar-mes es un hogar distinto.

Propósito: Mostrar cómo se anidan viviendas, hogares y personas en la base anual, qué variables identifican cada nivel y cuántas unidades hay en cada año.

Unidad
filas (personas-mes), hogares-mes, viviendas, conteos
Periodo
2022-01 a 2025-12
Cobertura
Total nacional (archivo completo de cada año)
Fuente
Cálculo propio con microdatos GEIH 2022 a 2025 (ANDA, DANE), script geih-lab/scripts/01_auditar_bases.py.
Notas:
  • Las bases anuales ya vienen con los módulos mensuales unidos; esta auditoría verifica el resultado del pegado, no el procedimiento.
  • PER es el año de la encuesta, no un identificador de persona.
  • La lectura de PERIODO como año, mes y semana es empírica: los caracteres 5 y 6 coinciden con MES.
  • DPTO y AREA vienen sin cero a la izquierda en el archivo; aquí se rellenan a dos caracteres.
  • Número de códigos distintos de AREA por año: 2022: 24, 2023: 32, 2024: 32, 2025: 32. En 2022 las filas de Amazonía y Orinoquía no tienen AREA; desde 2023 sí, así que una serie por ciudad cambia de dominio entre 2022 y 2023.
  • Santa Marta se identifica con AREA = 47 (cabecera municipal); el control santa_marta_* comprueba que esas filas son del Magdalena (DPTO 47) y de cabecera (CLASE 1).
  • P3271 (sexo al nacer) es la única variable de sexo en las cuatro bases; P6020 no existe en ellas.
Ver los datos de la figura
TablaEstructura de las bases anuales por año
AñoFilas (personas-mes)ColumnasHogares-mesViviendasViviendas con más de un hogarFilas repetidas con DIRECTORIO + ORDENFilas repetidas con DIRECTORIO + SECUENCIA_P + ORDEN
2022919.459534304.459300.6493.0437.8570
2023860.802532293.511290.3252.5576.1870
2024829.683524290.968288.6041.9284.4300
2025817.550514292.942290.9251.6633.7050

Fuente: Cálculo propio con microdatos GEIH 2022 a 2025 (DANE), estructura_microdatos.json.

Casi todas las viviendas tienen un único hogar: en 2025 son 289.262 de 290.925. Las que tienen dos o más son 1.663, y la más poblada registra 7 hogares. Pese a ser pocas, son las que rompen las uniones mal planteadas, y su número cambia entre años: en 2022 había 3.043 viviendas con más de un hogar, de modo que el mismo error de llave pesa distinto según la base que se use.

Hay una comprobación sencilla de que la tabla conserva bien la jerarquía. Cada hogar tiene un jefe o jefa, y la variable de parentesco P6050 vale 1 para esa persona. Si los hogares están bien identificados, el número de jefes debe ser igual al de hogares. En 2025 hay 292.942 personas con P6050 == 1 y 292.942 hogares-mes: la misma cifra. En 2022 la coincidencia también es exacta (304.459 frente a 304.459).

Ficha del resultado · Estructura de la base anual de 2025 (filas, hogares, viviendas y llaves)
Periodo
2022-01 a 2025-12
Ámbito
Total nacional (archivo completo de cada año)
Microdatos
GEIH marco 2018, bases anuales apiladas 2022-2025 (geih_AAAA.csv)
Variables
DIRECTORIO, SECUENCIA_P, HOGAR, ORDEN, MES, PER, PERIODO, REGIS, FEX_C18, P6040, P6050, PT, PET, FT, FFT, OCI, DSI, DPTO, AREA, CLASE, P3271
Filtros
Ninguno: todas las filas de cada archivo.
Universo
Registros persona-mes de las bases públicas.
Factor
No aplica (conteos muestrales); FEX_C18 solo se usa en controles de constancia.
Método
Conteos sobre el archivo leído como texto con casteo explícito. Llave persona-mes DIRECTORIO + SECUENCIA_P + ORDEN; hogar-mes DIRECTORIO + SECUENCIA_P; vivienda DIRECTORIO. hogares_por_vivienda: número de hogares (k) por vivienda y cantidad de viviendas (n). personas_por_hogar: número de personas (k) por hogar-mes y cantidad de hogares (n). Los controles cuentan filas que violan cada regla (0 = se cumple en todo el archivo).
Código
geih-lab/scripts/01_auditar_bases.py · commit 0864525

Advertencias

  • Las bases anuales ya vienen con los módulos mensuales unidos; esta auditoría verifica el resultado del pegado, no el procedimiento.
  • PER es el año de la encuesta, no un identificador de persona.
  • La lectura de PERIODO como año, mes y semana es empírica: los caracteres 5 y 6 coinciden con MES.
  • DPTO y AREA vienen sin cero a la izquierda en el archivo; aquí se rellenan a dos caracteres.
  • Número de códigos distintos de AREA por año: 2022: 24, 2023: 32, 2024: 32, 2025: 32. En 2022 las filas de Amazonía y Orinoquía no tienen AREA; desde 2023 sí, así que una serie por ciudad cambia de dominio entre 2022 y 2023.
  • Santa Marta se identifica con AREA = 47 (cabecera municipal); el control santa_marta_* comprueba que esas filas son del Magdalena (DPTO 47) y de cabecera (CLASE 1).
  • P3271 (sexo al nacer) es la única variable de sexo en las cuatro bases; P6020 no existe en ellas.

Estas cifras describen el archivo, no la población, y por eso no tienen referente oficial con el cual compararse. Su validación es interna: que las llaves sean únicas, que los jefes coincidan con los hogares y, al final del capítulo, que el total expandido reproduzca la población que publica el DANE.

Las llaves que identifican cada fila#

Una llave es la combinación de variables que identifica una fila sin ambigüedad. En la GEIH hay tres variables de identificación que importan. DIRECTORIO identifica la vivienda y tiene siempre siete dígitos. SECUENCIA_P numera los hogares dentro de la vivienda. ORDEN numera las personas dentro del hogar. La consecuencia de esa jerarquía es que ORDEN vuelve a empezar en cada hogar: en una vivienda con dos hogares hay dos personas con ORDEN == 1, una por hogar.

La forma de comprobar una llave es contar cuántas filas sobran si se exige que cada combinación sea única. El bloque siguiente lo hace con la función de lectura del laboratorio para tres combinaciones.

Python
import polars as pl
from geihlab.lectura import leer_geih

df = leer_geih(2025, ["DIRECTORIO", "SECUENCIA_P", "HOGAR", "ORDEN", "FEX_C18"])
print(df.height, "filas")
print(df.schema)

def duplicados(d: pl.DataFrame, llaves: list[str]) -> int:
    """Filas que sobran si cada combinación de llaves fuera única."""
    return d.height - d.select(llaves).unique().height

for llaves in (["DIRECTORIO", "ORDEN"],
               ["DIRECTORIO", "SECUENCIA_P", "ORDEN"],
               ["DIRECTORIO", "SECUENCIA_P", "ORDEN", "MES"]):
    print(" + ".join(llaves), "->", duplicados(df, llaves))
Ejecutado el 21 de octubre de 2026 desde la carpeta geih-lab (PYTHONPATH=.) sobre geih_2025.csv, con Python 3.14 y polars 1.39.3.
Texto
817550 filas
Schema({'MES': Int8, 'DIRECTORIO': Int64, 'SECUENCIA_P': Int16, 'HOGAR': Int16, 'ORDEN': Int16, 'FEX_C18': Float64})
DIRECTORIO + ORDEN -> 3705
DIRECTORIO + SECUENCIA_P + ORDEN -> 0
DIRECTORIO + SECUENCIA_P + ORDEN + MES -> 0
Salida obtenida al ejecutar el bloque anterior.

DIRECTORIO + ORDEN parece una llave razonable y no lo es: en 2025 deja 3.705 filas repetidas, y en 2022, 7.857. Son personas de viviendas con más de un hogar cuyo número de orden ya lo tiene alguien de otro hogar de la misma vivienda. En cambio, DIRECTORIO + SECUENCIA_P + ORDEN no repite ninguna fila en ninguno de los cuatro años, y agregarle MES tampoco cambia nada (la suma de duplicados de las dos llaves en los cuatro años es 0). Las llaves que usa el laboratorio, y que recomiendo, son estas:

  • persona-mes: DIRECTORIO + SECUENCIA_P + ORDEN, con MES como resguardo;
  • hogar-mes: DIRECTORIO + SECUENCIA_P;
  • vivienda-mes: DIRECTORIO.

El resguardo de MES es redundante con las bases actuales, por la razón que se explica enseguida, pero no cuesta nada y protege el código si algún día se apilan archivos con otra lógica. Lo que sí tiene costo es usar la llave incompleta en una unión. Si se une un módulo de hogar por DIRECTORIO solo, cada persona de una vivienda con dos hogares recibe dos filas de hogar, una de ellas ajena. Si se une un módulo de personas por DIRECTORIO + ORDEN, la persona 1 del hogar 1 se empareja también con la persona 1 del hogar 2, y lo mismo ocurre con cada número de orden que se repita entre hogares. En los dos casos el resultado tiene más filas que la base, y parte de ellas combina las características de una persona con las respuestas de otra. El aumento de filas se detecta comparando conteos antes y después de unir; la mezcla de respuestas no se ve a simple vista, y por eso el script de construcción del laboratorio se niega a unir cuando la llave de un módulo no es única.

El factor de expansión obedece a la misma jerarquía. La metodología lo establece para el factor de calibración:

Concepto DANE

“Nótese que los w_k son iguales para todos los individuos de la vivienda y diferentes entre viviendas”.

Fuente: Metodología GEIH V11, p. 20

El capítulo 2 comprobó esa propiedad en la base de 2025. Aquí interesa como control de estructura: en los cuatro años, el número de viviendas-mes con más de un valor de FEX_C18 es 0. Es una buena prueba para cualquier base reconstruida, porque una unión defectuosa que mezcle viviendas suele romperla.

Cada vivienda aparece en un solo mes#

Dentro de un año, ningún DIRECTORIO aparece en más de un mes: la suma de casos en las cuatro bases es 0. Entre años consecutivos tampoco hay coincidencias: las viviendas comunes entre 2022 y 2023, entre 2023 y 2024 y entre 2024 y 2025 suman 0. Por eso, en la base anual, el número de viviendas distintas (290.925 en 2025) es a la vez el número de viviendas-mes.

Lo que esto dice del diseño hay que leerlo con cuidado. Para evitar el agotamiento de la fuente, la metodología rota cada año la medida de tamaño, nombre que la versión anterior de la metodología daba al segmento (Metodología GEIH V9, p. 24): al año siguiente se encuesta una medida de tamaño vecina que ninguna operación estadística haya encuestado en, como mínimo, los dos años anteriores (Metodología GEIH V11, p. 17). La ausencia de viviendas comunes entre años es coherente con esa regla, pero la base pública no permite distinguir entre una vivienda que no se volvió a visitar y una que se volvió a visitar con otro código.

Interpretación

Para el analista, la conclusión práctica es la misma en ambos casos: con las bases públicas no se puede seguir a un hogar en el tiempo. La GEIH, en esta forma, no es un panel. Cada mes es una muestra distinta, y la base anual es la unión de doce muestras mensuales independientes. Cualquier análisis de transiciones (de desocupado a ocupado, de informal a formal) que se intente con estos archivos compara grupos distintos de personas, no a las mismas personas en dos momentos.

Esta estructura tiene una consecuencia que reaparece al final del capítulo. Como cada fila es una persona en un mes, y el factor de esa fila representa a una porción de la población de ese mes, sumar el factor de todo el año da unas doce veces la población del país. El total anual se obtiene promediando los totales mensuales, no sumándolos.

Variables que parecen identificadores#

Junto a las llaves verdaderas hay variables cuyo nombre o aspecto invita a usarlas como identificadores y que no lo son. La tabla 3.1 resume lo que la auditoría del laboratorio encontró en cada una.

Tabla 3.1Variables de identificación y lo que son en las bases 2022 a 2025
VariableQué esEvidencia en los archivos
DIRECTORIOVivienda0 viviendas en más de un mes; 0 comunes entre años consecutivos
SECUENCIA_P y HOGARHogar dentro de la vivienda; son la misma variableFilas en que difieren, sumadas en los cuatro años: 0
ORDENPersona dentro del hogarReinicia en cada hogar; por eso no basta con DIRECTORIO
PEREl año de la encuesta, no la personaUn único valor por archivo: 2022; 2023; 2024; 2025
PERIODOAño, mes y semana de recolección (lectura empírica)Caracteres 5 y 6 distintos de MES, sumados en los cuatro años: 0
REGISConstante sin poder de identificaciónUn solo valor en todos los años: 10
MESMes de recolección, de 1 a 12, sin cero a la izquierdaDoce valores en cada año

Fuente: Cálculo propio con microdatos GEIH 2022 a 2025 (DANE), estructura_microdatos.json, bloque controles.

Nota: La lectura de PERIODO como año, mes y semana es empírica: ninguna fuente consultada documenta la estructura de ese código.

Con PER el riesgo está en el nombre, que sugiere “persona”. En un proyecto previo del autor figuraba entre las variables de identificación, tipada como entero, y el error no se notaba porque, al tomar un único valor por archivo, no rompía ninguna unión; simplemente no aportaba nada. PERIODO guarda más información de la que su nombre sugiere. En la base de 2025 tiene siempre ocho caracteres, el quinto y el sexto coinciden con el mes en todas las filas (en las cuatro bases, de hecho) y los dos últimos recorren 52 valores en el año, lo que se lee como la semana de recolección. Esa lectura es coherente con que “el período de recolección es semanal para las 32 ciudades capitales de departamento con sus áreas metropolitanas” (Metodología GEIH V11, p. 14), pero es una inferencia del laboratorio y no una definición oficial.

Python
import polars as pl
from geihlab.lectura import leer_geih

df = leer_geih(2025, ["PER", "PERIODO", "REGIS"])
print("PER:", df["PER"].unique().to_list())
print("REGIS:", df["REGIS"].unique().to_list())
print("largo de PERIODO:", df["PERIODO"].str.len_chars().unique().to_list())
sufijo = df["PERIODO"].str.slice(6, 2).cast(pl.Int8)
print("últimos dos dígitos:", sufijo.min(), "a", sufijo.max(), "|", sufijo.n_unique(), "valores")
print("caracteres 5 y 6 distintos de MES:",
      df.filter(pl.col("PERIODO").str.slice(4, 2).cast(pl.Int8) != pl.col("MES")).height)
Ejecutado el 21 de octubre de 2026 desde la carpeta geih-lab (PYTHONPATH=.) sobre geih_2025.csv, con Python 3.14 y polars 1.39.3.
Texto
PER: [2025]
REGIS: ['10']
largo de PERIODO: [8]
últimos dos dígitos: 1 a 52 | 52 valores
caracteres 5 y 6 distintos de MES: 0
Salida obtenida al ejecutar el bloque anterior.

Leer el archivo sin perder información#

Los archivos anuales son texto separado por comas, con punto decimal. Ningún valor del factor contiene coma, así que reemplazar comas por puntos, un paso que aparece en algunos códigos que circulan, sobra en estas bases. Lo que sí hace falta es decidir cómo se interpretan los tipos, y aquí la regla del laboratorio es leer todo como texto y castear después, columna por columna y por nombre.

La razón es que la inferencia automática de tipos decide mirando las primeras filas, y en la GEIH las primeras filas no son representativas. Una columna de códigos puede parecer numérica y perder sus ceros a la izquierda; otra puede traer un punto aislado miles de filas más abajo y hacer fallar la lectura, o peor, convertirse entera en texto sin aviso. Con infer_schema_length=0, polars lee cada columna como texto y el código declara qué tipo tiene cada variable que se usa. El fragmento siguiente es la parte central de la función de lectura del laboratorio.

Pythongeih-lab/geihlab/lectura.py
def _expr_tipo(col: str) -> pl.Expr:
    c = pl.col(col)
    if col in INDICADORAS:
        return c.str.strip_chars().cast(pl.Int8).fill_null(0)
    if col in _ENTEROS:
        return c.str.strip_chars().cast(_ENTEROS[col])
    if col in _DECIMALES:
        return c.str.strip_chars().cast(pl.Float64)
    if col in _RELLENO_2:
        return c.str.strip_chars().str.zfill(2)
    if col in _RELLENO_4:
        return c.str.strip_chars().str.zfill(4)
    return c

# dentro de leer_geih(anio, columnas):
lf = (
    pl.scan_csv(
        ruta,
        encoding="utf8-lossy",
        infer_schema_length=0,
        null_values=["", "."],
    )
    .select(presentes)
    .with_columns([_expr_tipo(c).alias(c) for c in presentes])
)
Fragmento; el módulo completo define los conjuntos _ENTEROS, _DECIMALES, _RELLENO_2, _RELLENO_4 e INDICADORAS y exige los 12 meses.

Cada rama de _expr_tipo responde a un problema concreto de los archivos, y las tres subsecciones que siguen los recorren. La función, además, selecciona las columnas por nombre antes de castear, así que nunca lee las más de quinientas columnas de la base cuando un cálculo necesita ocho, y falla con un error explícito si se le pide una columna que no existe en ese año.

Ceros a la izquierda#

Los códigos de departamento de la División Político-Administrativa tienen dos dígitos: Antioquia es 05, Atlántico 08, Magdalena 47. En los archivos de la GEIH, DPTO viene sin el cero: Antioquia aparece como “5”. Lo mismo pasa con AREA, el código de ciudad, y con la rama de actividad a dos dígitos RAMA2D_R4. Quien filtra por el código oficial obtiene cero filas, sin error.

Python
import polars as pl
from geihlab.lectura import ruta_anio

# El archivo tal como viene, todo como texto y sin limpieza
crudo = pl.scan_csv(ruta_anio(2025), encoding="utf8-lossy", infer_schema_length=0)

print(crudo.select(
    (pl.col("DPTO") == "05").sum().alias("DPTO == '05'"),
    (pl.col("DPTO") == "5").sum().alias("DPTO == '5'"),
    (pl.col("DPTO").str.zfill(2) == "05").sum().alias("zfill(2) == '05'"),
).collect().row(0, named=True))
Ejecutado el 21 de octubre de 2026 desde la carpeta geih-lab (PYTHONPATH=.) sobre geih_2025.csv, con Python 3.14 y polars 1.39.3.
Texto
{"DPTO == '05'": 0, "DPTO == '5'": 47177, "zfill(2) == '05'": 47177}
Salida obtenida al ejecutar el bloque anterior.

El filtro con el código oficial devuelve cero filas de Antioquia; con el código tal como está en el archivo, o con el código rellenado a dos caracteres, aparecen todas. El problema se repite al cruzar la base con cualquier tabla externa que use los códigos con cero, como un diccionario o una tabla de nombres de departamento: el cruce falla para Antioquia y Atlántico, los dos departamentos de código menor que 10, y funciona para los otros 31 códigos, lo que hace el error difícil de ver en un resumen. El laboratorio rellena DPTO, AREA y RAMA2D_R4 a dos caracteres al leer, y todo el libro filtra el Magdalena como DPTO == "47".

El código de ocupación OFICIO_C8 plantea una versión más sutil del mismo problema. Sigue la clasificación CIUO-08 con cuatro dígitos, y en 2025 llega con cuatro caracteres en el 99,88 % de las filas de ocupados. Los que llegan con tres son del grupo que empieza por cero, las ocupaciones militares, sin ese cero: en 2025 son 409 filas con los códigos 110, 210, 310, que completos serían 0110, 0210 y 0310. Hay además 7 filas con el código “0”. La regla oficial de informalidad toma los dos primeros caracteres de un código de cuatro, así que hay que rellenar a cuatro, y solo a cuatro.

Resultado reproducido

Calculado con los microdatos de la GEIH por el laboratorio del libro.

Una línea de código y un cuarto de punto de informalidad

Con OFICIO_C8 rellenado a cuatro caracteres, la proporción de ocupados informales de 2025 calculada con la regla del DANE es 55,7188 % y coincide con la cifra derivada del anexo oficial. Si el mismo código se rellena a ocho caracteres, un descuido fácil cuando se copia un preprocesamiento pensado para otra variable, cambian de clasificación 724 filas y la proporción baja a 55,4702 %, −0,2487 p.p.. No rellenar da en 2025 el mismo resultado que rellenar a cuatro (diferencia de 0,0000 p.p.), pero solo por cómo caen los datos de estos años: sin el cero, un código “210” se corta como 21 y no como 02, y en un trabajador por cuenta propia ese corte puede decidir la clasificación.

Ficha del resultado · Proporción de informalidad nacional, 2025 (regla oficial con OFICIO_C8 a 4 caracteres)Coincide
Periodo
2025
Ámbito
Total nacional
Microdatos
GEIH marco 2018, bases anuales 2022 a 2025 (12 meses cada una)
Variables
OCI, FEX_C18, MES, DPTO, AREA, CLASE, P3271, P6430, P6100, P6110, P6450, P6920, P6930, P6940, RAMA2D_R4, P3045S1, P3046, P3069, P6765, P3065, P3066, P3067, P3067S1, P3067S2, P6775, P3068, OFICIO_C8, PER
Filtros
OCI == 1. Magdalena: DPTO == '47' tras rellenar a 2 caracteres. Santa Marta: AREA == '47'.
Universo
Población ocupada
Factor
FEX_C18, promedio de los 12 totales mensuales
Método
Regla oficial: traducción línea a línea de la hoja Código_STATA del anexo anex-GEIHEISS-oct-dic2025.xlsx (actualizado el 12 de febrero de 2026); EI = 0 informal. Se verificó que la hoja Código_SAS clasifica igual. Proporción = informales / ocupados, con totales anuales como promedio de los totales mensuales. Oficial derivado: promedio de los cuatro trimestres calendario (ene-mar, abr-jun, jul-sep, oct-dic) de la serie de trimestres móviles del anexo. Regla no_cotiza (NO oficial): formal si P6100 == 1 y P6920 == 1, para todos los ocupados.
Anualización
Cociente de los promedios anuales de numerador y denominador
Muestra
358.029 filas-mes en el universo del indicador
Código
geih-lab/scripts/03_informalidad.py · commit 0864525

Contraste con la cifra oficial

Propio55,7188 %
Oficial55,7188 % (derivado de celdas del anexo)
Diferencia−0,0000 (tolerancia 0,0001)
CV aproximado0,29 % (cota inferior, sin el diseño completo)

Diferencia menor que la tolerancia frente a un valor oficial con al menos cuatro decimales y el mismo método.

La diferencia de un cuarto de punto parece pequeña frente a una proporción de más de 55 %, y por eso mismo es peligrosa: está dentro de lo que muchos aceptarían como “cerca de la cifra oficial”. El capítulo 6 muestra en qué parte de la regla entra el oficio, qué ocupados cambian de clasificación y por qué omitir el relleno tampoco es seguro, y el capítulo 8 vuelve sobre este caso para mostrar por qué una diferencia pequeña no equivale a una validación.

Puntos, vacíos e indicadoras#

La GEIH marca la ausencia de dato de dos maneras. La habitual es la celda vacía. La otra es un punto aislado, que recuerda la forma en que algunos paquetes estadísticos escriben el faltante y que aparece en algunas columnas de ocupación y de rama (OFICIO1_C8, OFICIO2_C8, RAMA4D_D_R4) y en algunos bloques de preguntas de años recientes. Si no se declara como faltante, el punto impide castear la columna a número o, si la columna se deja como texto, se cuenta como una categoría más.

Cuál de las dos marcas recibe cada fila no es cuestión de azar. El bloque siguiente toma OFICIO1_C8, uno de los códigos de ocupación de la base, y cruza el tipo de valor (código, punto o vacío) con la clasificación laboral de la fila.

Python
import polars as pl
from geihlab.lectura import ruta_anio

crudo = pl.scan_csv(ruta_anio(2025), encoding="utf8-lossy", infer_schema_length=0)

estado = (
    pl.when(pl.col("OFICIO1_C8") == ".").then(pl.lit("punto"))
    .when(pl.col("OFICIO1_C8").is_null()).then(pl.lit("vacío"))
    .otherwise(pl.lit("código"))
    .alias("OFICIO1_C8")
)
grupo = (
    pl.when(pl.col("OCI") == "1").then(pl.lit("ocupado"))
    .when(pl.col("DSI") == "1").then(pl.lit("desocupado"))
    .when(pl.col("FFT") == "1").then(pl.lit("fuera de la FT"))
    .otherwise(pl.lit("menor de 15"))
    .alias("grupo")
)
tabla = crudo.select(grupo, estado).group_by("grupo", "OFICIO1_C8").len()
for fila in tabla.sort("len", descending=True).collect().iter_rows():
    print(fila)

try:
    crudo.select(pl.col("OFICIO1_C8").cast(pl.Int32)).collect()
except pl.exceptions.InvalidOperationError:
    print("el casteo directo falla: '.' no es un número")
Ejecutado el 21 de octubre de 2026 desde la carpeta geih-lab (PYTHONPATH=.) sobre geih_2025.csv, con Python 3.14 y polars 1.39.3.
Texto
('ocupado', 'vacío', 358029)
('fuera de la FT', 'punto', 254523)
('menor de 15', 'vacío', 163711)
('desocupado', 'código', 41287)
el casteo directo falla: '.' no es un número
Salida obtenida al ejecutar el bloque anterior.

Cada grupo recibe una sola marca. Los desocupados tienen un código; los ocupados y los menores de 15 años, celda vacía; las personas fuera de la fuerza de trabajo, un punto. El número de filas con punto, 254.523, es exactamente el número de filas con FFT == 1 en 2025. Las dos marcas significan “no aplica”, pero para grupos distintos, y probablemente reflejan dos caminos del flujo del cuestionario. Ninguna fuente consultada documenta esa diferencia, así que el laboratorio las trata igual, como faltantes (null_values=["", "."]), y conserva la información del grupo a través de las variables de clasificación, que es donde debe estar.

Las variables de clasificación laboral tienen su propia convención. PT, PET, FT, FFT, OCI y DSI valen 1 cuando la persona pertenece al grupo y vienen vacías cuando no; no hay ceros. Multiplicar el factor por una indicadora vacía da nulo, y según la herramienta ese nulo se ignora en la suma o contamina el resultado. El laboratorio convierte el vacío en 0 al leer (fill_null(0)), con lo que la suma del factor por la indicadora es directamente el total expandido del grupo. Que el vacío signifique “no pertenece” y no “no se sabe” está respaldado por las identidades de la última sección: si fueran datos faltantes, las identidades no se cumplirían fila por fila.

Texto libre y codificación de caracteres#

Los archivos son casi enteramente ASCII. La excepción son las columnas de texto libre, las respuestas a preguntas del tipo “¿cuál?”, donde aparecen eñes y tildes codificadas en Latin-1, que no son UTF-8 válido. La lectura del laboratorio usa encoding="utf8-lossy", que reemplaza cada byte inválido por el carácter de reemplazo U+FFFD en lugar de fallar. El bloque siguiente cuenta en qué columnas ocurre eso en 2025.

Python
import polars as pl
from geihlab.lectura import ruta_anio

# Con utf8-lossy, cada byte que no es UTF-8 válido se vuelve U+FFFD
crudo = pl.scan_csv(ruta_anio(2025), encoding="utf8-lossy", infer_schema_length=0)
columnas = crudo.collect_schema().names()
conteo = crudo.select(
    pl.col(c).str.contains("\ufffd", literal=True).sum().alias(c) for c in columnas
).collect().row(0, named=True)
afectadas = sorted(c for c, v in conteo.items() if v)
print(len(afectadas), "de", len(columnas), "columnas:")
print(afectadas)
Ejecutado el 21 de octubre de 2026 desde la carpeta geih-lab (PYTHONPATH=.) sobre geih_2025.csv, con Python 3.14 y polars 1.39.3.
Texto
19 de 514 columnas:
['P1661S4A1', 'P1880S1', 'P1881S1', 'P3086S1', 'P3386S1', 'P5090S1', 'P6240S1', 'P6260S1A1', 'P6310S1', 'P6430S1', 'P6765S1', 'P6780S1', 'P6810S1', 'P6830S1', 'P6880S1', 'P6915S1', 'P7028S1', 'P7140S9A1', 'P7240S1']
Salida obtenida al ejecutar el bloque anterior.

Son columnas cuyo contenido es texto escrito por el encuestador, con tildes y eñes, y casi todas terminan en S1. Ninguna de las variables de identificación, clasificación laboral, factor o ingreso que usa el libro está en la lista, y por eso la lectura con reemplazo es inocua para sus cálculos. Quien necesite leer el texto de esas columnas debe abrir el archivo con encoding="latin1", teniendo presente lo que dice la sección sobre privacidad: en esas mismas columnas aparecen a veces datos que no deberían circular.

Columnas que cambian entre 2022 y 2025#

Las cuatro bases comparten 502 columnas. El resto aparece o desaparece de un año a otro: la base de 2022 tiene 534 columnas y la de 2025, 514. La figura 3.2 lista las 44 columnas que no están en los cuatro años, agrupadas por su patrón de presencia.

Figura 3.2Columnas que aparecen o desaparecen entre 2022 y 2025Entre 2024 y 2025 desaparecen 22 columnas y aparecen 12; entre 2022 y 2023 solo desaparecen 2.
Columnas que no están en los cuatro años (44), agrupadas por patrón de presencia.
Columna2022202320242025
De 2022 a 2024; ausente desde 2025 · 22 columnas
DSCYpresentepresentepresenteausente
P1661S1presentepresentepresenteausente
P1661S1A1presentepresentepresenteausente
P1661S2presentepresentepresenteausente
P1661S2A1presentepresentepresenteausente
P3051S1presentepresentepresenteausente
P3052S1presentepresentepresenteausente
P3147S1presentepresentepresenteausente
P3147S10presentepresentepresenteausente
P3147S10A1presentepresentepresenteausente
P3147S11presentepresentepresenteausente
P3147S2presentepresentepresenteausente
P3147S3presentepresentepresenteausente
P3147S4presentepresentepresenteausente
P3147S5presentepresentepresenteausente
P3147S6presentepresentepresenteausente
P3147S7presentepresentepresenteausente
P3147S8presentepresentepresenteausente
P3147S9presentepresentepresenteausente
P3366presentepresentepresenteausente
P4000presentepresentepresenteausente
P6290presentepresentepresenteausente
Solo en 2025 · 12 columnas
P1661S5ausenteausenteausentepresente
P1661S5A1ausenteausenteausentepresente
P1661S6ausenteausenteausentepresente
P1661S6A1ausenteausenteausentepresente
P1881S1ausenteausenteausentepresente
P3071S3ausenteausenteausentepresente
P3072S2ausenteausenteausentepresente
P4005ausenteausenteausentepresente
P5222S11ausenteausenteausentepresente
P7140S9A1ausenteausenteausentepresente
P7240S1ausenteausenteausentepresente
P7280S1ausenteausenteausentepresente
De 2022 a 2023; ausente desde 2024 · 8 columnas
CAMPESINApresentepresenteausenteausente
DIFICULTADpresentepresenteausenteausente
DISCAPACIDADpresentepresenteausenteausente
LGB_NUMERICApresentepresenteausenteausente
LGB_SECTORESpresentepresenteausenteausente
LGBT_NUMERICApresentepresenteausenteausente
P7330presentepresenteausenteausente
TRANS_NUMERICApresentepresenteausenteausente
Solo en 2022 · 2 columnas
P3044presenteausenteausenteausente
P3084presenteausenteausenteausente

Propósito: Identificar qué columnas no existen en todos los años, para no construir una serie 2022 a 2025 con una variable que falta en alguno.

Unidad
presencia de la columna (verdadero o falso)
Periodo
2022 a 2025
Cobertura
Encabezados completos de las cuatro bases anuales
Fuente
Comparación propia de los encabezados de las bases anuales GEIH 2022 a 2025 (ANDA, DANE), script geih-lab/scripts/01_auditar_bases.py.
Notas:
  • Columnas comunes a los cuatro años: 502 (no se listan).
  • Columnas por año: 2022: 534, 2023: 532, 2024: 524, 2025: 514.
  • El orden de las columnas también cambia entre años: nunca seleccionar por posición.
  • Que una columna conserve su nombre no garantiza que conserve la pregunta o la codificación; eso exige el diccionario de cada año.
Ver los datos de la figura

De 2022 a 2023 desaparecen P3044, P3084 y no aparece ninguna.

De 2023 a 2024 desaparecen CAMPESINA, DIFICULTAD, DISCAPACIDAD, LGBT_NUMERICA, LGB_NUMERICA, LGB_SECTORES, P7330, TRANS_NUMERICA y no aparece ninguna.

De 2024 a 2025 desaparecen DSCY, P1661S1, P1661S1A1, P1661S2, P1661S2A1, P3051S1, P3052S1, P3147S1, P3147S10, P3147S10A1, P3147S11, P3147S2, P3147S3, P3147S4, P3147S5, P3147S6, P3147S7, P3147S8, P3147S9, P3366, P4000, P6290; aparecen P1661S5, P1661S5A1, P1661S6, P1661S6A1, P1881S1, P3071S3, P3072S2, P4005, P5222S11, P7140S9A1, P7240S1, P7280S1.

Tres grupos de cambios afectan el análisis del mercado laboral de forma directa. El primero son las variables derivadas de enfoque diferencial (CAMPESINA, DISCAPACIDAD, DIFICULTAD, LGBT_NUMERICA y las demás de su bloque), que están en 2022 y 2023 y no en 2024 ni 2025. La metodología señala que con los datos de la GEIH marco 2018 se generan indicadores de mercado laboral para la población en condición de discapacidad, con autorreconocimiento campesino y LGBT (Metodología GEIH V11, p. 3), de modo que la ausencia de esas columnas en las bases recientes no significa que el tema haya salido de la encuesta. Lo que desaparece es la variable ya construida. Si las preguntas de origen siguen en el formulario, habría que reconstruirla con el diccionario del año, y este libro no ha verificado que se pueda.

El segundo grupo está en 2025. Sale P4000 y entra P4005; sale DSCY, presente de 2022 a 2024; y el bloque P1661 de ayudas en dinero cambia de composición, con la salida de P1661S1 y P1661S2 y la entrada de P1661S5 y P1661S6. Las fuentes consultadas no documentan qué miden DSCY ni P4005, y el libro no hace suposiciones al respecto. Para ingresos no laborales por transferencias, el cambio del bloque P1661 rompe cualquier serie que se arme con los nombres de 2022.

El tercero no aparece en la figura, porque afecta el orden de las columnas y no sus nombres. Ese orden varía entre años, y en 2023 las variables de enfoque diferencial aparecen al final del encabezado y no donde estaban en 2022. Un código que seleccione “la columna 37” lee P3147S5 de 2022 a 2024 y P1906S1 en 2025, sin ningún error. La regla del laboratorio es seleccionar siempre por nombre, y la función de lectura tiene una opción explícita para las ausencias: con faltantes="nulo" crea la columna vacía en el año en que no existe, en lugar de fallar, para que el análisis decida qué hacer con ese año en lugar de descubrirlo tarde.

Explicación del autor

Lo que la figura no garantiza

Que una columna conserve su nombre en los cuatro años no prueba que conserve la pregunta, las opciones de respuesta ni la población a la que se le pregunta. La matriz de presencia sirve como primer filtro, y la comparabilidad exige más. Para cada variable que entre en una serie, la comprobación completa es abrir el diccionario y el cuestionario de cada año y comparar el texto de la pregunta y sus categorías.

El diccionario y sus límites#

El DANE acompaña las bases con un diccionario de datos, y la metodología describe su función.

Concepto DANE

“Se cuenta con el diccionario de datos de la GEIH para facilitar el manejo de las bases que se publican y está dirigido tanto a usuarios internos como externos. El diccionario contiene el código y las variables correspondientes a cada una de las preguntas del formulario”.

Fuente: Metodología GEIH V11, p. 27

El diccionario es indispensable y, a la vez, hay que usarlo con método. El que empleé al comenzar este trabajo era una compilación de diccionarios de varios años en una sola hoja, sin columna de año ni de módulo. Ese formato tiene tres problemas que encontrará cualquiera que arme su propia compilación. Una misma variable aparece varias veces con definiciones o categorías distintas, sin forma de saber cuál corresponde a qué año. Las variables nuevas de un año posterior a la compilación no aparecen: la de este trabajo no cubría las columnas que entran en 2025. Y algunas variables construidas por el DANE que son centrales para el libro, como INGLABO, FEX_C18 o las indicadoras de fuerza de trabajo, figuran sin categorías ni descripción de cómo se construyen.

La recomendación es descargar de ANDA el diccionario de cada año que se use y consultarlo con el año a la vista. Dos detalles prácticos completan la recomendación. Los códigos del diccionario se escriben con su cero (“05”, “08”), de modo que cruzarlo con la base exige rellenar DPTO primero. Y los nombres de variable no siempre coinciden en mayúsculas entre el diccionario y la base: un cruce sensible a mayúsculas no encuentra Campesina cuando la columna se llama CAMPESINA.

El caso que mejor ilustra los límites del diccionario es el sexo. En las cuatro bases la única variable de sexo es P3271, “sexo al nacer”, y no hay ninguna columna P6020, el nombre que buscan algunos códigos escritos para otras bases; este libro no verificó en qué versiones de la encuesta se usaba ese nombre. P3271 toma solo los valores 1 y 2, y la compilación del diccionario no traía sus categorías. La presentación del rediseño muestra en el módulo de caracterización “Sexo al nacer: 1. Femenino 2. Masculino” (Enfoque conceptual GEIH 2022, p. 60), pero los datos se comportan como si 1 fuera hombre y 2 mujer, y el laboratorio adopta esa lectura por la evidencia que sigue.

Resultado reproducido

Calculado con los microdatos de la GEIH por el laboratorio del libro.

Con P3271 == 1 como hombres, la tasa de desocupación anual de 2025 de ese grupo es 6,9936 % y coincide hasta el cuarto decimal con la cifra derivada de la hoja por sexo del anexo mensual del DANE. Con P3271 == 2 la tasa es 11,4416 %, que coincide con la de las mujeres. Si la codificación fuera la inversa, cada código tendría que reproducir la tasa del otro sexo, y las dos tasas están separadas por 4,4 puntos. Aun así, la correspondencia es una inferencia muy respaldada y no una definición leída en el diccionario oficial del año, y el libro la presenta como tal. El capítulo 5 retoma la comparación con las dos tasas.

Ficha del resultado · TD de los hombres, total nacional, 2025 (P3271 = 1)Coincide
Periodo
2025
Ámbito
Total nacional · Hombres
Microdatos
GEIH marco 2018, bases anuales apiladas 2022-2025 (geih_AAAA.csv)
Variables
DIRECTORIO, MES, DPTO, AREA, CLASE, P3271, P6040, FEX_C18, PT, PET, FT, FFT, OCI, DSI
Filtros
Ámbito: ninguno (nacional), DPTO == '47' (Magdalena), AREA == '47' (Santa Marta). Sexo: P3271 == 1 (hombres), P3271 == 2 (mujeres).
Universo
PT: todas las personas; PET: PET == 1 (15 años y más); FT: FT == 1; OC: OCI == 1; DS: DSI == 1; PFFT: FFT == 1. TGP y TO sobre la PET; TD sobre la FT.
Factor
FEX_C18 (factor mensual), promedio de 12 totales mensuales
Método
Mensual: suma de FEX_C18 por indicadora en el mes; tasas como cociente de totales. Anual, metodo_anual = promedio_de_totales para poblaciones y razon_de_promedios para tasas (cociente de los promedios anuales); metodo_anual = promedio_de_tasas: promedio simple de las 12 tasas mensuales. n: filas-mes del universo del indicador (denominador para tasas). cv_cota_inf: geihlab.precision.cv_aproximado; para PT no se calcula y para promedio_de_tasas tampoco.
Anualización
Cociente de los promedios anuales de numerador y denominador
Muestra
217.157 filas-mes en el universo del indicador
Código
geih-lab/scripts/02_indicadores_laborales.py · commit 0864525

Contraste con la cifra oficial

Propio6,9936 %
Oficial6,9936 % (derivado de celdas del anexo)
Diferencia0,0000 (tolerancia 0,0001)
CV aproximado1,31 % (cota inferior, sin el diseño completo)

Diferencia menor que la tolerancia frente a un valor oficial con al menos cuatro decimales y el mismo método.

Ficha del resultado · TD de las mujeres, total nacional, 2025 (P3271 = 2)Coincide
Periodo
2025
Ámbito
Total nacional · Mujeres
Microdatos
GEIH marco 2018, bases anuales apiladas 2022-2025 (geih_AAAA.csv)
Variables
DIRECTORIO, MES, DPTO, AREA, CLASE, P3271, P6040, FEX_C18, PT, PET, FT, FFT, OCI, DSI
Filtros
Ámbito: ninguno (nacional), DPTO == '47' (Magdalena), AREA == '47' (Santa Marta). Sexo: P3271 == 1 (hombres), P3271 == 2 (mujeres).
Universo
PT: todas las personas; PET: PET == 1 (15 años y más); FT: FT == 1; OC: OCI == 1; DS: DSI == 1; PFFT: FFT == 1. TGP y TO sobre la PET; TD sobre la FT.
Factor
FEX_C18 (factor mensual), promedio de 12 totales mensuales
Método
Mensual: suma de FEX_C18 por indicadora en el mes; tasas como cociente de totales. Anual, metodo_anual = promedio_de_totales para poblaciones y razon_de_promedios para tasas (cociente de los promedios anuales); metodo_anual = promedio_de_tasas: promedio simple de las 12 tasas mensuales. n: filas-mes del universo del indicador (denominador para tasas). cv_cota_inf: geihlab.precision.cv_aproximado; para PT no se calcula y para promedio_de_tasas tampoco.
Anualización
Cociente de los promedios anuales de numerador y denominador
Muestra
182.159 filas-mes en el universo del indicador
Código
geih-lab/scripts/02_indicadores_laborales.py · commit 0864525

Contraste con la cifra oficial

Propio11,4416 %
Oficial11,4416 % (derivado de celdas del anexo)
Diferencia0,0000 (tolerancia 0,0001)
CV aproximado1,14 % (cota inferior, sin el diseño completo)

Diferencia menor que la tolerancia frente a un valor oficial con al menos cuatro decimales y el mismo método.

Variables geográficas y variables de diseño ausentes#

Tres variables ubican a cada persona en el territorio. DPTO trae 33 códigos en cada año, que incluyen San Andrés y los departamentos de la Amazonía y la Orinoquía. En estos últimos solo se encuesta la cabecera de la capital, de acuerdo con las exclusiones del universo (Metodología GEIH V11, p. 13), y eso se refleja en los archivos.

AREA identifica la ciudad o el área metropolitana, con el mismo código numérico del departamento: 47 es Santa Marta. Fuera de esas ciudades viene vacía (224.252 filas en 2025), nunca aparece en filas de centros poblados y rural disperso (0 casos) y, cuando existe, siempre coincide con DPTO (0 discrepancias). Su cobertura cambió entre años. En 2022 tiene 24 códigos, que según una consulta de los códigos presentes corresponden a las 23 cabeceras de ciudades que enumera la metodología (Metodología GEIH V11, p. 14) más San Andrés (88). Desde 2023 tiene 32, porque las ocho capitales de la Amazonía y la Orinoquía, que en 2022 venían sin AREA, pasan a tenerla. Una serie “por ciudades” que use AREA tiene, por tanto, dominios distintos en 2022 y en los años siguientes. Para Santa Marta no hay ambigüedad: sus 24.548 filas de 2025 son todas del Magdalena y todas de cabecera, coherente con que la metodología la incluya entre las cabeceras de ciudades.

CLASE distingue la cabecera (1) del resto (2). La metodología define la cabecera como el área delimitada por el perímetro censal, en cuyo interior está la sede administrativa del municipio, y el resto como el área “cubierta por el centro poblado y rural disperso” (Metodología GEIH V11, p. 13). El código 2 de la base no debe confundirse con la “clase 2” que la misma página asigna a los centros poblados dentro de la clasificación geográfica: en los archivos, CLASE solo toma los valores 1 y 2, y el 2 reúne centros poblados y rural disperso. El diccionario que usé al comenzar este trabajo etiqueta las dos categorías como urbano y rural; en este libro se usan los términos de la metodología, cabecera y centros poblados y rural disperso, porque una cabecera municipal pequeña no es lo que la mayoría de lectores entiende por urbano.

Igual de importante es lo que falta. Las bases no traen ninguna variable del diseño muestral: no hay estrato de diseño, ni código de municipio, ni segmento. La columna P4030S1A1, que a veces se confunde con un estrato, es el estrato socioeconómico para la tarifa de energía, una pregunta sobre el servicio público de la vivienda, sin relación con la estratificación del muestreo. DPTO, CLASE y AREA son dominios geográficos y no estratos. Esas ausencias responden a la anonimización: la metodología enumera el municipio, el segmento y el estrato de diseño entre las variables de identificación que no se manejan en las bases de acceso público (Metodología GEIH V11, p. 27), una lista que el capítulo 2 transcribe completa. La consecuencia es que, sin estratos ni unidades secundarias de muestreo, los errores estándar con el diseño del DANE no se pueden reproducir con estos archivos. El capítulo 8 explica cómo leer la precisión que publica el DANE y qué aproximación propia se puede hacer, rotulada como tal.

Lo que la base no trae por privacidad#

La falta del municipio tiene una consecuencia práctica inmediata: con la base pública no se puede producir ninguna cifra para un municipio que no sea una de las ciudades que identifica AREA, ni siquiera una mal estimada, y aun para esas ciudades lo que se obtiene es la cabecera o el área metropolitana que la variable delimita, no el municipio completo. La anonimización llega también a las personas. Según la metodología, los nombres y apellidos no están en las bases públicas, la fecha de nacimiento se entrega solo con mes y año y se anonimiza el nombre de la empresa donde trabaja la persona (Metodología GEIH V11, p. 28). Los archivos lo confirman: el nacimiento viene en dos columnas, P6030S1 para el mes y P6030S3 para el año, sin día.

Hay un hueco que la anonimización no cubre y que el analista debe manejar por su cuenta. Las columnas de texto libre de la sección sobre codificación contienen lo que el encuestador escribió como respuesta a preguntas del tipo “¿cuál?”, y en algunas de ellas aparecen nombres propios de terceros. Por esa razón este libro no reproduce texto libre de los microdatos en ninguna parte, el laboratorio no lo usa ni lo publica, y recomiendo hacer lo mismo en cualquier trabajo derivado: los resultados se publican agregados.

De filas a personas: el primer total expandido#

Con la base bien leída, el primer cálculo con significado poblacional es la población total. La variable PT vale 1 en todas las filas de los cuatro años, de modo que contar personas expandidas es sumar el factor. El capítulo 2 ya mostró que esas sumas reproducen la población del DANE; aquí interesa escribir el cálculo completo, porque tiene dos pasos y el segundo es el que suele hacerse mal.

El primer paso es el total de cada mes. Si wim es el factor FEX_C18 de la fila i en el mes m y yim la indicadora del grupo que se quiere contar, el total expandido del mes es la suma, sobre las filas de ese mes, del factor por la indicadora:

Tm=∑i∈smwim·yim(3.1)

El segundo paso es llevarlo al año. Como cada mes es una muestra distinta que representa a la población de ese mes, el total anual es el promedio de los doce totales mensuales:

Tanual=112∑m=112Tm(3.2)

La ecuación 3.2 es una convención de este libro para totales anuales, no la transcripción de un estimador anual del DANE, que la metodología no documenta en el texto disponible. Con los doce meses presentes, el promedio de los totales es lo mismo que sumar el factor de todo el año y dividir entre 12. Esa equivalencia se rompe si falta un mes, y por eso la función de lectura del laboratorio falla cuando una base no tiene los doce: dividir entre 12 una suma de once meses subestima la población en una doceava parte, algo más de 8 %, sin ningún aviso.

Python
import polars as pl
from geihlab.lectura import leer_geih

df = leer_geih(2025, ["FEX_C18", "PT", "PET", "FT", "FFT", "OCI", "DSI"])

# Total expandido de cada mes: suma del factor por la indicadora
mensual = (
    df.group_by("MES")
    .agg((pl.col("FEX_C18") * pl.col("PT")).sum().alias("PT"))
    .sort("MES")
)
for mes, pt in mensual.iter_rows():
    print(f"{mes:>2}  {pt:,.0f}")

# Promedio anual: válido solo porque están los 12 meses
assert mensual.height == 12
print("promedio 2025:", f"{mensual['PT'].mean():,.1f}")

# Identidades de la clasificación, fila por fila
print("FT != OCI + DSI:", df.filter(pl.col("FT") != pl.col("OCI") + pl.col("DSI")).height)
print("PET != FT + FFT:", df.filter(pl.col("PET") != pl.col("FT") + pl.col("FFT")).height)
Ejecutado el 21 de octubre de 2026 desde la carpeta geih-lab (PYTHONPATH=.) sobre geih_2025.csv, con Python 3.14 y polars 1.39.3.
Texto
 1  51,831,449
 2  51,874,862
 3  51,914,421
 4  51,957,935
 5  52,000,467
 6  52,045,001
 7  52,082,200
 8  52,126,583
 9  52,170,223
10  52,211,996
11  52,254,976
12  52,296,261
promedio 2025: 52,063,864.5
FT != OCI + DSI: 0
PET != FT + FFT: 0
Salida obtenida al ejecutar el bloque anterior (separador de miles de Python, con coma).

Los totales mensuales crecen de forma suave a lo largo del año. Es lo esperable, porque la calibración mensual ajusta el factor a proyecciones de población de mitad de cada mes (Metodología GEIH V11, p. 20). La comparación decisiva es con el DANE: la fila “Población total” de la hoja del total nacional del anexo mensual publica esos mismos totales. La tabla 3.2 los pone lado a lado para 2025.

Tabla 3.2Suma mensual de FEX_C18 frente a la población total del anexo, 2025
MesSuma de FEX_C18 (miles)Anexo DANE (miles)Diferencia (miles)Celda
enero51.831,44951.831,4490,000KD23
febrero51.874,86251.874,8620,000KE23
marzo51.914,42151.914,4210,000KF23
abril51.957,93551.957,9350,000KG23
mayo52.000,46752.000,4670,000KH23
junio52.045,00152.045,0010,000KI23
julio52.082,20052.082,2000,000KJ23
agosto52.126,58352.126,5830,000KK23
septiembre52.170,22352.170,2230,000KL23
octubre52.211,99652.211,9960,000KM23
noviembre52.254,97652.254,9760,000KN23
diciembre52.296,26152.296,2610,000KO23

Fuente: Cálculo propio con microdatos GEIH 2025; oficial: Anexo GEIH ago. 2026, hoja Total nacional, fila 23.

Nota: El control se hizo para los 48 meses de enero de 2022 a diciembre de 2025; la mayor diferencia absoluta es 0,000 miles de personas. El anexo publica la población en miles con tres decimales, es decir, a la persona.

Los doce meses de 2025 coinciden a la persona, y lo mismo pasa en los meses de 2022 a 2024 que resumió el capítulo 2, desde enero de 2022, cuando la suma del factor da 50.254,112 miles. Con los totales mensuales validados, el promedio anual de 2025 es el primer total expandido del libro.

Resultado reproducido

Calculado con los microdatos de la GEIH por el laboratorio del libro.

La población total de 2025, como promedio de los doce totales mensuales expandidos con FEX_C18, es 52.063,865 miles de personas. El promedio de las doce celdas mensuales del anexo da 52.063,865 miles; la diferencia, 0,000492 miles, es menor que una persona.

Ficha del resultado · Población total, total nacional, 2025 (promedio de los 12 totales mensuales)Coincide
Periodo
2025
Ámbito
Total nacional
Microdatos
GEIH marco 2018, bases anuales apiladas 2022-2025 (geih_AAAA.csv)
Variables
DIRECTORIO, MES, DPTO, AREA, CLASE, P3271, P6040, FEX_C18, PT, PET, FT, FFT, OCI, DSI
Filtros
Ámbito: ninguno (nacional), DPTO == '47' (Magdalena), AREA == '47' (Santa Marta). Sexo: P3271 == 1 (hombres), P3271 == 2 (mujeres).
Universo
PT: todas las personas; PET: PET == 1 (15 años y más); FT: FT == 1; OC: OCI == 1; DS: DSI == 1; PFFT: FFT == 1. TGP y TO sobre la PET; TD sobre la FT.
Factor
FEX_C18 (factor mensual), promedio de 12 totales mensuales
Método
Mensual: suma de FEX_C18 por indicadora en el mes; tasas como cociente de totales. Anual, metodo_anual = promedio_de_totales para poblaciones y razon_de_promedios para tasas (cociente de los promedios anuales); metodo_anual = promedio_de_tasas: promedio simple de las 12 tasas mensuales. n: filas-mes del universo del indicador (denominador para tasas). cv_cota_inf: geihlab.precision.cv_aproximado; para PT no se calcula y para promedio_de_tasas tampoco.
Anualización
Promedio de los 12 totales mensuales
Muestra
817.550 filas-mes en el universo del indicador
Código
geih-lab/scripts/02_indicadores_laborales.py · commit 0864525

Contraste con la cifra oficial

Propio52.063,865 miles de personas
Oficial52.063,865 miles de personas (derivado de celdas del anexo)
Diferencia0,000 (tolerancia 0,001)

Diferencia menor que la tolerancia frente a un valor oficial con al menos cuatro decimales y el mismo método.

Esta coincidencia tiene un alcance preciso. Prueba que el archivo se leyó completo, que el factor se interpretó bien y que sus sumas mensuales reproducen la población con la que el DANE publica sus cifras nacionales de cada mes, lo que es coherente con que FEX_C18 sea el factor de la calibración mensual. No prueba que el promedio de doce meses sea el estimador anual del DANE: el referente anual de la ficha es una derivación propia a partir de las celdas mensuales del anexo. Tampoco dice nada de la precisión de los indicadores laborales, ni de los dominios que el DANE calibra de otra forma. La metodología describe una segunda calibración, anual y por departamentos (Metodología GEIH V11, p. 20), cuyo factor no viene en la base pública; por eso, como se verá en el capítulo 9, los totales anuales del Magdalena calculados con FEX_C18 no coinciden exactamente con los publicados.

Dos identidades para comprobar la lectura#

Las indicadoras de clasificación laboral permiten una segunda comprobación, esta vez fila por fila y sin necesidad de factor. La fuerza de trabajo se divide en ocupados y desocupados, y la población en edad de trabajar se divide en fuerza de trabajo y población fuera de la fuerza de trabajo. Si la base se leyó bien, cada fila debe cumplir FT = OCI + DSI y PET = FT + FFT, nadie puede ser ocupado y desocupado a la vez, la PET debe coincidir con tener 15 años o más y ningún menor de 15 puede estar en la fuerza de trabajo. El capítulo 4, Quién trabaja y quién busca explica las definiciones detrás de cada grupo.

En los cuatro años, el número total de filas que violan alguna de esas cinco condiciones es 0. La edad mínima con PET == 1 es 15 y la máxima con PET == 0, 14, en todos los años. Que las identidades se cumplan sin excepción respalda dos decisiones de lectura a la vez: que el vacío de las indicadoras significa “no pertenece” y que filtrar por la variable PET o por P6040 >= 15 da exactamente el mismo universo en 2022 a 2025. Superados estos controles, el capítulo 5, Las tasas del mercado laboral puede dedicarse a las tasas.

Ejercicios#

Ejercicio 3.1

Encontrar el error de llave

Una vivienda simulada tiene dos hogares. La tabla de personas y la tabla de hogar están abajo; las cifras son inventadas con fines didácticos y no provienen de la GEIH. Alguien une la tabla de hogar a la de personas usando solo DIRECTORIO. ¿Cuántas filas obtiene y qué está mal?

Tabla 3.3SimuladoPersonas y hogares de una vivienda simulada
TablaDIRECTORIOSECUENCIA_PORDENEdadTenencia
Personas90000011145
Personas90000011243
Personas90000011312
Personas90000012171
Personas90000012268
Hogar90000011Arriendo
Hogar90000012Propia
Ver una pista

Cuente cuántas filas de hogar coinciden con cada persona si la unión se hace solo por DIRECTORIO.

Ver la respuesta

La unión por DIRECTORIO solo empareja cada persona con todos los hogares de su vivienda. La vivienda tiene dos hogares, así que cada una de las cinco personas recibe dos filas del módulo de hogar y el resultado tiene diez filas en lugar de cinco. Las personas del hogar 1 quedan duplicadas con la tenencia del hogar 2, y viceversa. Al expandir, la vivienda aporta el doble de personas.

La unión correcta es por DIRECTORIO + SECUENCIA_P, la llave de hogar, y devuelve las cinco filas con la tenencia que corresponde a cada hogar. Es la misma razón por la que DIRECTORIO + ORDEN repite filas en los archivos reales: la jerarquía vivienda, hogar y persona exige las tres variables para la persona y las dos primeras para el hogar.

Ejercicio 3.2

Un filtro que devuelve cero filas

Un analista lee la base de 2025 con todas las columnas como texto y filtra Antioquia con DPTO == "05". Obtiene cero filas, sin error. Explique por qué y proponga la corrección que menos errores produce en el resto del análisis.

Ver una pista

Mire cómo está escrito el código de Antioquia en el archivo, no en el diccionario.

Ver la respuesta

En el archivo, DPTO viene sin el cero a la izquierda: Antioquia es “5”, no “05”. Leído como texto, DPTO == "05" no encuentra ninguna fila; en la base de 2025, el mismo filtro con “5” o con el código rellenado a dos caracteres encuentra 47.177, como muestra la salida de la sección sobre ceros a la izquierda. Leer DPTO como número tampoco es buena solución, porque obliga a recordar la conversión en cada cruce con tablas que usan el código con cero. Lo más seguro es rellenar a dos caracteres al leer, como hace geihlab/lectura.py, y escribir siempre los códigos oficiales.

Ejercicio 3.3

Comprobar las identidades en 2024

Lea la base de 2024 con la función del laboratorio y verifique, fila por fila, que FT = OCI + DSI, que PET = FT + FFT y que PET vale 1 exactamente cuando P6040 es 15 o más. Diga qué decisión de lectura respaldan esas comprobaciones.

Ver una pista

Basta cambiar el año en el último bloque de código de la sección sobre el primer total expandido y agregar la condición de edad.

Ver la respuesta

Con leer_geih(2024, ["P6040", "PT", "PET", "FT", "FFT", "OCI", "DSI"]) y los mismos filtros, las dos identidades se cumplen en todas las filas: la auditoría del laboratorio registra para 2024 0 filas con FT distinto de OCI + DSI, 0 con PET distinto de FT + FFT y 0 en que PET no coincide con tener 15 años o más.

Si al hacerlo obtiene un número distinto de cero, lo más probable es que no haya convertido el vacío de las indicadoras en 0: con nulos, la comparación FT != OCI + DSI devuelve nulo en lugar de falso y el filtro se comporta de forma distinta según la herramienta.

Lo que queda abierto#

Varias piezas de este capítulo se apoyan en evidencia empírica y no en documentación oficial, y es justo dejarlas señaladas. La más importante es el paso de los módulos mensuales de ANDA a la base anual: el script que lo hace está escrito y probado con módulos sintéticos, pero no se ha validado con módulos reales. La lectura de PERIODO como semana de recolección, la de P3271 como 1 hombre y 2 mujer, y el significado de DSCY y P4005 dependen del diccionario oficial de cada año, que este libro no tuvo a la vista: las dos primeras están bien respaldadas por los datos; las dos últimas quedan sin interpretar. Tampoco se verificó la lista de archivos de la descarga de ANDA año por año.

Los totales y las tasas nacionales de los capítulos siguientes no dependen de esas lagunas: usan variables cuyo comportamiento se comprobó en las cuatro bases, y sus totales mensuales coinciden con los del DANE. La excepción es la lectura de P3271, de la que dependen todos los cortes por sexo; por eso esos cortes se contrastan con las cifras oficiales por sexo allí donde el DANE las publica. Quien extienda el trabajo a otras variables, o a años anteriores a 2022, debe repetir la auditoría de este capítulo antes de calcular: el capítulo 10, Laboratorio de reproducción describe cómo correr los mismos controles sobre cualquier base.