feat(eda): series temporales + rigor anti-data-mining + PDF movil + /eda + benchmark issues
Bloque del grupo eda (sesion ausente EDA-benchmark): - 8 funciones nuevas: adf_kpss_stationarity, acf_pacf, stl_decompose, to_returns, fdr_correction, suggest_reexpression, exploratory_caveats, render_eda_pdf - integracion: profile_table (run_series, emit_pdf), association_matrix (FDR Benjamini-Hochberg), render_eda_markdown (secciones series/reexpresion/caveats) - slash commands /eda y /capitulos - issues 0173-0177: mejoras del /eda derivadas del benchmark sobre 12 datasets reales (outlier_pct x100, periodo estacional, FK inference, render models, tipos id-like) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
---
|
||||
name: suggest_reexpression
|
||||
kind: function
|
||||
lang: py
|
||||
domain: datascience
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "def suggest_reexpression(stats: dict) -> dict"
|
||||
description: "Sugiere la re-expresion de la escalera de potencias de Tukey (none/log/log1p/sqrt/square/cube/box-cox/yeo-johnson) que mas simetriza una columna numerica, a partir de su skew y su dominio (ceros/negativos). Pura: razona por reglas, NO ejecuta la transformacion. Devuelve recomendacion + razon legible + alternativas ordenadas."
|
||||
tags: [statistics, eda, reexpression, transform, skew, tukey, ladder-of-powers, box-cox, yeo-johnson, python]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: []
|
||||
params:
|
||||
- name: stats
|
||||
desc: "dict con los estadisticos de una columna numerica (sub-bloque `numeric` de un ColumnProfile del grupo eda, o el ColumnProfile completo). Usa `skew` (obligatorio), y `min`/`zero_pct`/`negative_pct` cuando esten para determinar el dominio. Si recibe un ColumnProfile entero, baja a su clave `numeric`."
|
||||
output: "dict con `recommended` (nombre de la transformacion o None si falta skew), `ladder_power` (exponente conceptual de la escalera de Tukey: 1.0 raw, 0.5 sqrt, 0.0 log, None para data-driven), `reason` (explicacion legible), `alternatives` (lista ordenada de {transform, ladder_power, reason}), `skew` (el usado) y `note` (vacio en caso normal; mensaje si la entrada es incompleta o el dominio es desconocido). Nunca lanza excepcion."
|
||||
tested: true
|
||||
tests: ["test_aproximadamente_simetrica_recomienda_none", "test_positiva_fuerte_todo_positivo_recomienda_log", "test_positiva_moderada_todo_positivo_recomienda_sqrt", "test_positiva_con_ceros_fuerte_recomienda_log1p", "test_positiva_con_negativos_recomienda_yeo_johnson", "test_negativa_fuerte_todo_positivo_recomienda_cube", "test_negativa_moderada_todo_positivo_recomienda_square", "test_dominio_desconocido_recomienda_yeo_johnson_con_nota", "test_acepta_columnprofile_completo_con_numeric_anidado", "test_skew_ausente_devuelve_nota", "test_stats_vacio_devuelve_nota", "test_no_dict_no_lanza", "test_skew_no_numerico_devuelve_nota"]
|
||||
test_file_path: "python/functions/datascience/suggest_reexpression_test.py"
|
||||
file_path: "python/functions/datascience/suggest_reexpression.py"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```python
|
||||
from datascience import suggest_reexpression
|
||||
|
||||
# Columna estrictamente positiva con cola derecha larga -> log.
|
||||
stats = {"skew": 2.3, "min": 1.0, "zero_pct": 0.0, "negative_pct": 0.0}
|
||||
out = suggest_reexpression(stats)
|
||||
out["recommended"] # -> "log"
|
||||
out["ladder_power"] # -> 0.0 (escalon p=0 de la escalera de Tukey)
|
||||
out["reason"] # -> "skew = 2.3 (cola derecha..., fuerte) y todos los valores > 0: log comprime..."
|
||||
[a["transform"] for a in out["alternatives"]] # -> ["box-cox", "sqrt"]
|
||||
|
||||
# Con valores negativos, log/Box-Cox no valen -> Yeo-Johnson.
|
||||
suggest_reexpression({"skew": 1.8, "min": -4.0, "negative_pct": 20.0})["recommended"] # -> "yeo-johnson"
|
||||
|
||||
# Funciona directo sobre el sub-bloque `numeric` de describe_numeric:
|
||||
# col["numeric"] = {"skew": ..., "min": ..., "zero_pct": ..., "negative_pct": ...}
|
||||
suggest_reexpression(col["numeric"])
|
||||
```
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Cuando un EDA ya detecto que una columna numerica esta sesgada (|skew| alto en el
|
||||
bloque `numeric` de `describe_numeric` / `detect_distribution_type`) y quieres el
|
||||
siguiente paso de Tukey: que transformacion la simetriza. Cierra el gap entre
|
||||
"detecto skew" y "sugiere la re-expresion". Util antes de modelar (muchos modelos
|
||||
asumen ~normalidad o varianza estable) y para enriquecer un reporte EDA con una
|
||||
recomendacion accionable por columna. NO la uses si solo quieres el valor del skew
|
||||
(eso ya lo da `describe_numeric`).
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Es **pura**: NO ejecuta la transformacion, solo decide cual sugerir. Aplicarla es
|
||||
trabajo del caller (numpy/scipy/sklearn) si decide seguir la recomendacion.
|
||||
- Necesita `skew`. Sin el devuelve `recommended=None` + `note` (no lanza).
|
||||
- El dominio (ceros/negativos) se infiere de `min`, `zero_pct` y `negative_pct`. Si
|
||||
ninguno esta presente, el dominio es desconocido y sugiere `yeo-johnson` (opcion
|
||||
segura para cualquier rango) con una nota; pasale al menos `min` para una decision
|
||||
mas fina (log vs sqrt vs Box-Cox).
|
||||
- `zero_pct`/`negative_pct` se interpretan como ">0 = hay ceros/negativos"; la escala
|
||||
(fraccion 0-1 o porcentaje 0-100) es indiferente para la decision.
|
||||
- Umbrales: |skew|<0.5 -> `none`; 0.5-1.0 -> moderada; >=1.0 -> fuerte. Son la
|
||||
convencion habitual, no una verdad absoluta — un caller puede recomputar con el
|
||||
`skew` que se devuelve.
|
||||
- `log`/`Box-Cox` exigen datos estrictamente positivos; con ceros usa `log1p`; con
|
||||
negativos o ceros, `Yeo-Johnson`. La funcion ya aplica estas reglas por ti.
|
||||
Reference in New Issue
Block a user