7fa19d65db
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>
5.0 KiB
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. |
|
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 |
|
python/functions/datascience/missingness_overview_test.py | python/functions/datascience/missingness_overview.py |
|
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_rowses 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_rowses simplemente esa longitud.- Solo el valor exacto
1cuenta 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 == 0los porcentajes salen0.0.