fix(eda): bugs de bajo riesgo del benchmark (H1,H5,H12,H13,H14) + tests faltantes
- H1: render_eda_markdown ya no aplica doble x100 a outlier_pct (336% -> real) - H5: profile_database filtra base_tables_only (excluye VIEWs; sakila 21->16) - H12: suggest_reexpression salta columnas no-continuas - H13: to_returns/profile_table elige retornos (financiera) vs diferencias (fisica) - H14: test de regresion ATTACH sqlite via information_schema - +8 tests de las funciones eda nuevas (acf_pacf, adf_kpss, ...). 77 tests verdes - L/M (H2,H3,H4,H6,H7,H8,H9,H10,H11) quedan en issues 0174-0177 para revision Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
"""Tests para stl_decompose."""
|
||||
|
||||
import numpy as np
|
||||
|
||||
from stl_decompose import stl_decompose
|
||||
|
||||
|
||||
def _serie_estacional(n: int, period: int, trend: float, amp: float, seed: int) -> list:
|
||||
rng = np.random.default_rng(seed)
|
||||
return [
|
||||
trend * i + amp * np.sin(2 * np.pi * i / period) + rng.normal(0, 1)
|
||||
for i in range(n)
|
||||
]
|
||||
|
||||
|
||||
def test_serie_con_tendencia_y_estacionalidad():
|
||||
serie = _serie_estacional(n=120, period=12, trend=0.3, amp=10.0, seed=0)
|
||||
res = stl_decompose(serie, period=12)
|
||||
assert res["period"] == 12
|
||||
assert res["trend_strength"] > 0.5
|
||||
assert res["seasonal_strength"] > 0.5
|
||||
assert len(res["trend"]["values"]) == 120
|
||||
|
||||
|
||||
def test_fuerza_estacional_alta_con_estacionalidad_fuerte():
|
||||
# Amplitud estacional grande, ruido pequeno => seasonal_strength cercano a 1.
|
||||
serie = _serie_estacional(n=120, period=12, trend=0.05, amp=20.0, seed=1)
|
||||
res = stl_decompose(serie, period=12)
|
||||
assert res["seasonal_strength"] > 0.9
|
||||
|
||||
|
||||
def test_infiere_periodo_si_none():
|
||||
serie = _serie_estacional(n=120, period=12, trend=0.1, amp=10.0, seed=2)
|
||||
res = stl_decompose(serie) # period=None
|
||||
assert res.get("period_inferred") is True
|
||||
assert res["period"] is not None
|
||||
|
||||
|
||||
def test_serie_corta_devuelve_nota():
|
||||
# period=12 pero solo 20 puntos (< 2*period=24): nota, no descompone.
|
||||
serie = _serie_estacional(n=20, period=12, trend=0.1, amp=5.0, seed=3)
|
||||
res = stl_decompose(serie, period=12)
|
||||
assert "note" in res
|
||||
assert res["trend_strength"] is None
|
||||
|
||||
|
||||
def test_muestra_insuficiente_devuelve_nota():
|
||||
res = stl_decompose([1, 2, 3, 4, 5])
|
||||
assert res["n"] == 5
|
||||
assert res["note"] == "datos insuficientes"
|
||||
assert res["seasonal_strength"] is None
|
||||
|
||||
|
||||
def test_descarta_none_y_nan():
|
||||
serie = _serie_estacional(n=120, period=12, trend=0.2, amp=8.0, seed=4)
|
||||
sucio = []
|
||||
for i, v in enumerate(serie):
|
||||
sucio.append(v)
|
||||
if i % 30 == 0:
|
||||
sucio.append(None)
|
||||
sucio.append(float("nan"))
|
||||
res = stl_decompose(sucio, period=12)
|
||||
assert res["n"] == 120
|
||||
|
||||
|
||||
def test_serie_larga_resume_sin_values():
|
||||
# >200 puntos: las componentes vienen resumidas sin 'values'.
|
||||
serie = _serie_estacional(n=300, period=12, trend=0.1, amp=10.0, seed=5)
|
||||
res = stl_decompose(serie, period=12)
|
||||
assert res["trend"]["values"] is None
|
||||
assert "mean" in res["trend"]
|
||||
assert "note" in res["trend"]
|
||||
Reference in New Issue
Block a user