Skip to content

Instantly share code, notes, and snippets.

@robintux
Created February 2, 2026 13:54
Show Gist options
  • Select an option

  • Save robintux/3d144c3ad78521fffb1508dd4579d8ba to your computer and use it in GitHub Desktop.

Select an option

Save robintux/3d144c3ad78521fffb1508dd4579d8ba to your computer and use it in GitHub Desktop.
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