Files
fn_registry/dev/issues/0173-eda-correctitud-estadistica-critica.md
T
Egutierrez ebb00d8a42 chore(issues): cierra 0173-0177 (hallazgos del benchmark EDA resueltos en rondas 2-4)
Los 14 hallazgos H1-H14 del benchmark estan corregidos y verificados con re-corrida.
Commits: caf8c25d (S), c4cff5ed (render H4/H9), e142ef02 (comportamiento H2/H3/H6/H7/H8/H10/H11).

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

5.3 KiB
Raw Blame History

id, title, status, type, domain, scope, priority, depends, blocks, related, created, updated, tags
id title status type domain scope priority depends blocks related created updated tags
0173 EDA: bugs críticos de correctitud estadística (outlier_pct ×100, distribution_type por-skew) resuelto bugfix
registry-quality
registry-only alta
0174
0175
0176
0177
0068
2026-06-29 2026-06-29
eda
datascience
profile_table
render_eda_markdown
describe_numeric
benchmark

0173 — EDA: bugs críticos de correctitud estadística

Contexto

Un benchmark adversarial del workflow /eda sobre 12 datasets reales (29/06/2026, temp/eda_benchmark/EVALUATION.md) detectó que los estadísticos descriptivos base son correctos, pero el porcentaje de outliers que el report markdown muestra es imposible (supera el 100%, hasta 336%), engañando a un lector no experto con apariencia de autoridad.

Hallazgos cubiertos por este issue:

Hallazgo Severidad Evidencia del benchmark
H1 — outlier_pct por-columna >100% en el report markdown crítico wine-red chlorides 193.87%, density 112.57% (skew 0.07); titanic SibSp 336.70%, Fare 224.47%; seattle precipitation 253.25%
H11 — distribution_type por-skew etiqueta mal discretas/ordinales/multimodales bajo wine quality (6 valores) → "normal-ish"; precios BTC multimodales → "normal-ish" (skew 0.45)

Causa raíz de H1 (verificada en código, READ-ONLY)

EVALUATION.md propuso "corregir la fórmula en describe_numeric". Eso es incorrecto. Al leer el código:

  • python/functions/datascience/describe_numeric.py:113 calcula outlier_pct = 100.0 * n_outliers / n — ya en escala 0-100 y acotado a [0,100]. Está bien.
  • python/functions/datascience/render_eda_markdown.py:203-204 renderiza ese valor con _fmt_pct(val), y _fmt_pct (líneas 31-44) hace num * 100 porque asume que su input es una fracción 0-1. Resultado: doble ×100 (un 1.94 real se muestra como 193.87%).
  • El PDF (render_eda_pdf.py:296) usa _fmt_num(outlier_pct, 1) + "%" sin multiplicar — por eso el PDF muestra el outlier_pct correcto y el markdown no. El bug es exclusivo del renderer markdown.

El factor "19-40×" que observó el evaluador se debe a que comparaba contra outliers IQR (3-10%), mientras describe_numeric usa z-score (umbral 3.0, da menos outliers); pero el mecanismo del bug es el doble ×100, no la fórmula.

Tareas

  1. H1 (fix de 1 línea): en python/functions/datascience/render_eda_markdown.py:203-204, sustituir _fmt_pct(val) por un formateo que NO multiplique (p.ej. f"{_fmt_num(val, 2)}%"), porque numeric.outlier_pct ya viene en escala 0-100. No tocar describe_numeric.py (su fórmula es correcta).
  2. Auditar el resto de render_eda_markdown.py por si otro campo en escala 0-100 pasa por _fmt_pct (los *_pct del perfil base sí son fracciones 0-1 y deben seguir con _fmt_pct; solo numeric.outlier_pct está en escala 0-100). Documentar en el docstring de describe_numeric que outlier_pct está en 0-100 para evitar la confusión a futuro.
  3. H11: en python/functions/datascience/detect_distribution_type.py, no etiquetar por skew solamente: usar también nº de modos / cardinalidad y, cuando esté disponible, el test de normalidad Jarque-Bera (normality_tests.py, ya expuesto en models.normality vía run_eda_models). Una variable discreta/ordinal/multimodal no debe salir "normal-ish".
  4. Añadir/extender tests unitarios: describe_numeric_test.py (outlier_pct en [0,100]), render_eda_markdown_test.py (un perfil con outlier_pct=7.0 renderiza "7.00%", no "700%"), y un test de detect_distribution_type (discreta de 6 valores no se etiqueta "normal-ish"). Nota: hoy NO existe detect_distribution_type_test.py en python/functions/datascience/ — hay que crearlo (a confirmar el nombre canónico al implementar; el resto de tests citados sí existen).

Definition of Done

Escenario Tipo Comando / evidencia Resultado esperado
Golden: outlier_pct en rango e2e re-correr profile_table sobre temp/eda_benchmark/datasets/.../wine-red y leer el .md chlorides/density muestran outlier_pct en [0,100]% (no 193.87% / 112.57%)
Edge: skew alto real unit describe_numeric_test.py con datos de cola fuerte outlier_pct ≤ 100 y coherente con n_outliers/n
Edge: discreta ordinal unit detect_distribution_type_test.py con 6 valores discretos NO etiqueta "normal-ish"
Error: input vacío/no numérico unit describe_numeric([]) claves None, sin crash (contrato actual preservado)
Mecánica ./fn run describe_numeric_py_datascience, ./fn run render_eda_markdown_py_datascience tests verdes; fn index limpio

Re-correr el benchmark sobre wine-red y titanic y confirmar que ningún outlier_pct supera 100%.

Notas

Issue derivado de temp/eda_benchmark/EDA_ISSUES.md (consolidación del benchmark). H1 es el fix de mayor ratio impacto/esfuerzo del lote (una línea elimina los números imposibles que más minan la confianza del report). Hermanos: 0174 (series), 0175 (relational), 0176 (render), 0177 (tipos).

Resolucion (2026-06-29, sesion /ausente)

Resuelto y verificado con re-corrida del benchmark EDA. Commit principal: caf8c25d. Detalle en reports/ausente-eda-benchmark-2026-06-29.md y temp/eda_benchmark/EVALUATION.md.