fix(eda): hallazgos de comportamiento del benchmark (H2,H3,H6,H7,H8,H10,H11)

Ronda 4 (verificada con re-corrida sobre los datasets afectados):
- H2: stl_decompose deriva periodo de la frecuencia del indice (seattle period=365
  seasonal_strength=0.84; fin del period=2 espurio)
- H3+H10: infer_fk por senal de nombre (<X>Id->X.<X>Id) + excluir no-clave -> chinook
  111->9 FK, todas reales, cero absurdas, 16-27x mas rapido; base intacta (flag off->111)
- H6: association no computa eta2 si cardinalidad~=n (Ticket-Fare espurio fuera)
- H7: id secuencial monotono excluido de correlacion y PCA/KMeans (PassengerId fuera)
- H8: correlacion de series no estacionarias marcada espuria / sobre retornos
- H11: distribution_type usa modos/cardinalidad/normalidad (quality->discrete)
- 66 tests verdes

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Egutierrez
2026-06-29 06:37:47 +02:00
parent c4cff5ed5b
commit e142ef026d
12 changed files with 1028 additions and 36 deletions
+17 -4
View File
@@ -32,16 +32,29 @@ def _clean(values: list) -> list[float]:
def _infer_period(arr: np.ndarray, max_period: int) -> int | None:
"""Infiere el periodo estacional dominante via autocorrelacion.
"""Infiere el periodo estacional dominante via autocorrelacion del residuo detrended.
Busca el retardo (entre 2 y ``max_period``) que maximiza la autocorrelacion
de la serie. Devuelve None si no encuentra un pico claro (autocorrelacion
maxima por debajo de un umbral pequeno).
de la serie tras restarle su tendencia lineal. El detrend es clave: sobre una
serie con tendencia la autocorrelacion cruda decae monotonamente y el retardo
minimo (2) gana siempre, produciendo un ``period=2`` espurio que enmascara la
estacionalidad real (falso negativo). Quitando primero la recta de mejor ajuste
por minimos cuadrados, el lag ganador refleja el ciclo estacional y no la deriva.
Devuelve None si no encuentra un pico claro (autocorrelacion maxima por debajo
de un umbral pequeno).
"""
n = len(arr)
if n < 6:
return None
x = arr - arr.mean()
# Detrend lineal: resta la recta de mejor ajuste para que la tendencia no
# domine la autocorrelacion (si no, lag=2 gana siempre en series con deriva).
t = np.arange(n, dtype=float)
try:
slope, intercept = np.polyfit(t, arr, 1)
detrended = arr - (slope * t + intercept)
except (np.linalg.LinAlgError, ValueError):
detrended = arr - arr.mean()
x = detrended - detrended.mean()
denom = float(np.dot(x, x))
if denom == 0.0:
return None