--- id: missingness_overview_py_datascience name: missingness_overview kind: function lang: py domain: datascience version: "1.0.0" purity: pure signature: "def missingness_overview(null_mask) -> dict" description: "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." tags: [eda, missing, missingness, nulls, profiling, datascience, pure] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "" imports: [] example: | 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 tested: true tests: - "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" test_file_path: "python/functions/datascience/missingness_overview_test.py" file_path: "python/functions/datascience/missingness_overview.py" params: - name: null_mask desc: "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." output: "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 ```python 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`.