Files
fn_registry/python/functions/datascience/missingness_overview.md
T
egutierrez 7fa19d65db feat(eda): capítulo MISSINGNESS — patrones de datos faltantes (co-ocurrencia + MCAR/MAR)
Añade el capítulo `missingness` al motor AutomaticEDA, complemento natural de
`calidad`: donde calidad reporta cuánto falta por columna, este capítulo analiza
el PATRÓN de los nulos — dónde faltan y si las columnas faltan juntas
(co-ocurrencia de ausencias), la señal que distingue MCAR de MAR antes de imputar.

Capítulo (`chapters/missingness.py`), registrado en `chapters_registry.py` justo
tras `calidad`:
- Resumen global: % de celdas faltantes, columnas con nulos, filas completas vs
  incompletas.
- Ranking por columna (tabla + barras horizontales).
- Co-ocurrencia: correlación de las máscaras is-null entre columnas (heatmap +
  tabla de los pares que co-faltan, con co-faltantes y Jaccard).
- Patrones de fila más frecuentes (estilo matriz de missingno).
- Lectura MCAR/MAR exploratoria (heurística por correlación/solape de ausencias,
  no confirmatoria), que cita la evidencia concreta.
- Términos de glosario clicables: missingness, MCAR, MAR.

La máscara is-null por fila de TODAS las columnas (numéricas y categóricas) se
construye con un push-down DuckDB sobre ctx['db_path']/table (mismo patrón que el
capítulo agregación), con fallback a ctx['raw_numeric'] cuando no hay BD. Activa
solo si la tabla tiene nulos; si no, devuelve None.

Funciones nuevas del grupo `eda` (dominio datascience):
- extract_null_mask (impura): máscara is-null por fila vía query_fn.
- missingness_overview (pura): resumen global + filas completas/incompletas.
- missingness_correlation (pura): correlación de ausencias + pares + Jaccard,
  reutiliza pearson.
- missingness_row_patterns (pura): patrones de fila más comunes.
- missingness_corr_heatmap_figure / missingness_rank_bar_figure (impuras): figuras.

Verificado: EDA de titanic genera el capítulo en PDF + PPTX + MD con Cabin 77.1%,
Age 19.9% y la co-ocurrencia Age↔Cabin (158 filas). Suite completa de AutomaticEDA
+ render_automatic_eda en verde (125 passed); tests por función y por capítulo;
fn index sin error.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 20:38:39 +02:00

5.0 KiB

id, name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, example, tested, tests, test_file_path, file_path, params, output
id name kind lang domain version purity signature description tags uses_functions uses_types returns returns_optional error_type imports example tested tests test_file_path file_path params output
missingness_overview_py_datascience missingness_overview function py datascience 1.0.0 pure def missingness_overview(null_mask) -> dict Resumen de ausencias a nivel de dataset a partir de una máscara de nulos 0/1 por columna ({col: [1=falta, 0=presente]} alineada por fila). Calcula celdas y porcentaje de datos faltantes, cuántas columnas tienen algún nulo y cuántas filas son completas vs. incompletas. Estilo dict-no-throw del grupo eda: nunca lanza. Lectura defensiva — no-dict o dict vacío devuelve todo a 0; columnas no-lista se tratan como vacías; listas de longitud distinta se alinean a la longitud máxima rellenando la cola corta como presente (0); valores None/no-int cuentan como presente; sin ZeroDivisionError.
eda
missing
missingness
nulls
profiling
datascience
pure
false
from datascience.missingness_overview import missingness_overview mask = { "a": [1, 0, 0, 0, 1], "b": [1, 0, 1, 0, 0], "c": [0, 0, 0, 0, 1], } missingness_overview(mask) # n_missing_cells=5, missing_cell_pct≈33.33, complete_rows=2, incomplete_rows=3 true
test_cooccurrence_three_cols_exact
test_empty_dict_all_zero
test_output_keys_contract
test_not_a_dict_returns_zero
test_no_nulls_all_complete
test_none_values_treated_as_present
test_unequal_lengths_pad_with_max
test_columns_present_but_no_rows
test_never_raises_on_garbage
python/functions/datascience/missingness_overview_test.py python/functions/datascience/missingness_overview.py
name desc
null_mask Dict {col_name: [int 0/1, ...]} con la máscara de nulos por columna, alineada por fila (1 = el valor falta, 0 = el valor está presente). Normalmente todas las listas tienen la misma longitud = nº de filas. Lectura defensiva: si no es dict o está vacío se devuelve todo a 0; columnas cuyo valor no es lista/tupla se tratan como vacías; listas de longitud distinta se alinean a la longitud máxima (las posiciones inexistentes de las columnas más cortas cuentan como presentes, 0); valores None o no enteros cuentan como presentes.
Dict con exactamente 9 claves, todas siempre presentes (la función nunca lanza): n_rows (longitud de fila = longitud máxima entre columnas, 0 si vacío), n_cols (nº de columnas), n_cols_with_null (columnas con >=1 falta), n_missing_cells (suma total de 1s), missing_cell_pct (0-100 = n_missing_cells / (n_rows*n_cols) * 100), complete_rows (filas sin ninguna falta), incomplete_rows (filas con >=1 falta), complete_pct (0-100), incomplete_pct (0-100). Los porcentajes son 0.0 cuando el denominador es 0 (sin ZeroDivisionError).

Ejemplo

from datascience.missingness_overview import missingness_overview

# Máscara de nulos por columna: 1 = falta, 0 = presente, alineada por fila.
mask = {
    "a": [1, 0, 0, 0, 1],
    "b": [1, 0, 1, 0, 0],
    "c": [0, 0, 0, 0, 1],
}

missingness_overview(mask)
# {
#   "n_rows": 5,
#   "n_cols": 3,
#   "n_cols_with_null": 3,      # a, b y c tienen al menos una falta
#   "n_missing_cells": 5,       # 2 (a) + 2 (b) + 1 (c)
#   "missing_cell_pct": 33.33,  # 5 / (5*3) * 100
#   "complete_rows": 2,         # filas 1 y 3 sin ninguna falta
#   "incomplete_rows": 3,       # filas 0 (a&b), 2 (b), 4 (a&c)
#   "complete_pct": 40.0,       # 2 / 5 * 100
#   "incomplete_pct": 60.0,     # 3 / 5 * 100
# }

missingness_overview({})
# Todo a 0: {"n_rows": 0, "n_cols": 0, "n_cols_with_null": 0,
#            "n_missing_cells": 0, "missing_cell_pct": 0.0,
#            "complete_rows": 0, "incomplete_rows": 0,
#            "complete_pct": 0.0, "incomplete_pct": 0.0}

Cuando usarla

Úsala al perfilar un dataset cuando ya tienes una máscara de nulos 0/1 por columna (p. ej. derivada del paso de carga/perfilado del EDA) y quieres la foto global de ausencias en una llamada: cuánta proporción de celdas falta, cuántas columnas están afectadas y, sobre todo, cuántas filas quedan completas vs. incompletas. Es el bloque resumen del capítulo de calidad/missingness de un EDA, y la base para decidir estrategias de imputación o de borrado de filas. Como es pura y dict-no-throw, puedes alimentarla con la máscara tal cual sin validarla antes: entradas malformadas degradan a ceros en vez de romper el pipeline.

Gotchas

  • n_rows es la longitud máxima entre columnas. Con listas de longitud desigual, las posiciones que faltan en las columnas más cortas se cuentan como presentes (0); no se descartan filas. En el caso normal (todas las listas de igual longitud) n_rows es simplemente esa longitud.
  • Solo el valor exacto 1 cuenta como falta. None, 0, cadenas y cualquier otro valor se tratan como presentes. True (== 1) también cuenta como falta por la igualdad.
  • Porcentajes en escala 0-100, no fracciones. División por cero protegida: con n_rows*n_cols == 0 los porcentajes salen 0.0.