Created
February 2, 2026 13:54
-
-
Save robintux/3d144c3ad78521fffb1508dd4579d8ba to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def classical_decomposition(Y, m, model='additive'): | |
| """ | |
| Y: array de valores de la serie temporal | |
| m: periodicidad estacional (ej: 12 para mensual) | |
| model: 'additive' o 'multiplicative' | |
| """ | |
| n = len(Y) | |
| T = np.zeros(n) * np.nan # Tendencia | |
| # PASO 1: Estimación de Tendencia-Ciclo via MA centrada | |
| if m % 2 == 0: # Par: ej. 12 | |
| # MA de orden m seguida de MA(2) | |
| weights = np.ones(m + 1) | |
| weights[0] = 0.5 | |
| weights[-1] = 0.5 | |
| weights = weights / m | |
| half_width = m // 2 | |
| for t in range(half_width, n - half_width): | |
| T[t] = np.convolve(Y[t-half_width:t+half_width+1], weights, mode='valid') | |
| else: # Impar | |
| half_width = m // 2 | |
| for t in range(half_width, n - half_width): | |
| T[t] = np.mean(Y[t-half_width:t+half_width+1]) | |
| # PASO 2: Componente Estacional-Irregular | |
| if model == 'additive': | |
| SI = Y - T | |
| else: | |
| SI = Y / T | |
| # PASO 3: Índices Estacionales (promedio por periodo estacional) | |
| S = np.zeros(m) | |
| for k in range(m): | |
| # Índices correspondientes al periodo k (0-indexado) | |
| indices = [i for i in range(n) if i % m == k and not np.isnan(SI[i])] | |
| if model == 'additive': | |
| S[k] = np.mean(SI[indices]) | |
| else: | |
| S[k] = np.median(SI[indices]) # Mediana para robustez multiplicativa | |
| # Normalización | |
| if model == 'additive': | |
| S = S - np.mean(S) # Centrar en 0 | |
| else: | |
| S = S / np.prod(S)**(1/m) # Centrar geométricamente en 1 | |
| # Expandir S a longitud completa de la serie | |
| S_full = np.tile(S, (n // m) + 1)[:n] | |
| # PASO 4: Desestacionalización | |
| if model == 'additive': | |
| deseasonalized = Y - S_full | |
| else: | |
| deseasonalized = Y / S_full | |
| # PASO 5: Componente Irregular | |
| if model == 'additive': | |
| residual = Y - T - S_full | |
| else: | |
| residual = Y / (T * S_full) | |
| return T, S_full, residual, deseasonalized |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment