649de07d6b
Capítulo cat_distr del motor AutomaticEDA: distribuciones categóricas con explicación de entropía de Shannon, métricas de cardinalidad por columna (valores distintos, % distintos, total de filas, valores únicos, entropía y su máximo log2(k) + normalizada), tabla top-k y un donut de las categorías más comunes (top-k + «Otros»). Marca columnas id-like y dominadas. Delegadas a fn-constructor (grupo eda): - categorical_cardinality_block: deriva métricas de cardinalidad/entropía. - categorical_top_pie_figure: figura donut top-k + «Otros», leyenda lateral. Defensivo (dict-no-throw): None si no hay columnas categóricas; normaliza mode_pct a escala 0-100 (summarize_categorical lo emite como fracción). Tablas vía DataTable y figura perezosa: el paginador del núcleo garantiza no-corte en PDF y PPTX. Tests: golden + edge (sin categóricas) + anti-corte (label largo / muchas columnas) en ambos renderers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
6.0 KiB
6.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 | |||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| categorical_cardinality_block_py_datascience | categorical_cardinality_block | function | py | datascience | 1.0.0 | pure | def categorical_cardinality_block(cat: dict, n_rows: int) -> dict | Deriva métricas de cardinalidad listas para renderizar a partir de la salida de summarize_categorical para UNA columna categórica más el número total de filas. Calcula pct_distinct, entropy_max=log2(n_distinct), entropy_norm (recortada a [0,1]), n_singletons (sobre el top visible) y los flags id_like / dominated. NO recalcula la entropía ni reimplementa summarize_categorical: la consume. Estilo dict-no-throw del grupo eda — nunca lanza. |
|
false |
|
from categorical_cardinality_block import categorical_cardinality_block cat = {"top": [{"value": "a", "count": 5, "pct": 0.5}], "mode": "a", "mode_pct": 0.5, "n_distinct": 4, "entropy": 1.685, "imbalance": 5.0, "len_min": 1, "len_mean": 1.0, "len_max": 1} block = categorical_cardinality_block(cat, n_rows=10) | true |
|
python/functions/datascience/categorical_cardinality_block_test.py | python/functions/datascience/categorical_cardinality_block.py |
|
Dict con exactamente 16 claves, todas siempre presentes: n_distinct, n_rows, pct_distinct, entropy, entropy_max, entropy_norm, mode, mode_pct, imbalance, n_singletons, n_singletons_partial, len_min, len_mean, len_max, id_like, dominated. Valores None/False cuando no son derivables; la función nunca lanza. pct_distinct en escala 0-100. entropy_max=log2(n_distinct) (0.0 si n_distinct in {0,1}). entropy_norm=entropy/entropy_max recortada a [0,1]. n_singletons = nº de elementos de top con count==1 (None si top vacío). n_singletons_partial=True si n_distinct>len(top). id_like=pct_distinct>=99. dominated=mode_pct>=90. |
Ejemplo
from categorical_cardinality_block import categorical_cardinality_block
# Salida típica de summarize_categorical para una columna, con n_rows del dataset.
cat = {
"top": [
{"value": "a", "count": 5, "pct": 0.5},
{"value": "b", "count": 3, "pct": 0.3},
{"value": "c", "count": 1, "pct": 0.1},
{"value": "d", "count": 1, "pct": 0.1},
],
"mode": "a",
"mode_pct": 0.5,
"n_distinct": 4,
"entropy": 1.685, # Shannon en bits (<= log2(4) = 2.0)
"imbalance": 5.0,
"len_min": 1, "len_mean": 1.0, "len_max": 1,
}
categorical_cardinality_block(cat, n_rows=10)
# {
# "n_distinct": 4, "n_rows": 10,
# "pct_distinct": 40.0, # 4 / 10 * 100
# "entropy": 1.685,
# "entropy_max": 2.0, # log2(4)
# "entropy_norm": 0.8425, # 1.685 / 2.0, recortado a [0,1]
# "mode": "a", "mode_pct": 0.5,
# "imbalance": 5.0,
# "n_singletons": 2, # c y d con count == 1
# "n_singletons_partial": False, # top cubre los 4 distintos
# "len_min": 1, "len_mean": 1.0, "len_max": 1,
# "id_like": False, # pct_distinct 40 < 99
# "dominated": False, # mode_pct 0.5 < 90
# }
Cuando usarla
Úsala justo después de summarize_categorical, cuando vayas a renderizar el
bloque de cardinalidad de una columna categórica en un EDA: necesitas el ratio
de valores distintos (pct_distinct), la entropía normalizada al rango [0,1]
para comparar columnas con cardinalidades distintas, el conteo de singletons, y
las banderas heurísticas id_like (la columna parece un identificador) y
dominated (una sola categoría domina). Pásale el dict crudo de
summarize_categorical para esa columna y el n_rows total del dataset. No
reimplementa nada: solo deriva métricas de presentación a partir de lo ya
calculado.
Gotchas
mode_pctse pasa tal cual viene encat.summarize_categoricalproducemode_pctcomo fracción (0–1), no como porcentaje. El flagdominatedcomparamode_pct >= 90.0, así que con la salida cruda desummarize_categorical(fracciones)dominatedno se dispara: aliméntalo conmode_pcten escala 0–100 si quieres usar esa bandera. Solo el camino de fallback (cuandocatno traemode_pcty se deriva detop[0]['pct']) normaliza una fracción<= 1multiplicándola por 100.n_singletonssolo cubre eltopvisible. Sisummarize_categoricalse llamó contop_kpequeño, hay valores fuera del top; en ese cason_singletons_partialesTruepara avisar de que el conteo es parcial.pct_distinctesNonesin_rowses 0 oNone(no lanzaZeroDivisionError); por tantoid_likequedaFalseen ese caso.entropy_normesNonecuandoentropy_max <= 0(columna constante,n_distinct in {0,1}): no hay división por cero y no se inventa un 0/1.- No recalcula la entropía. Si
cat['entropy']es incoherente conn_distinct,entropy_normse recorta a[0,1]pero el valor de entrada no se corrige. boolno cuenta como número. UnTrue/Falseen una clave numérica decatse trata como ausente (None), por la guarda defensiva.