--- 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.