Decomposition splits a time series into three components: trend (long-term direction), seasonality (repeating patterns), and residual (noise). This reveals the structure hidden in raw data and guides model choice.
Ten years of monthly data: a trend, a seasonal wave of amplitude 10, and noise with standard deviation 3. Classical decomposition — a centred 2×12 moving average for the trend, then the average deviation for each month — recovers a seasonal amplitude of 9.18 and leaves residuals with a standard deviation of 2.67, close to the noise that was put in.
- Classical decomposition assumes the seasonal pattern never changes; STL lets it evolve.
- The centred moving average leaves no trend estimate for the first and last six months — exactly the most recent data you care about.
- Additive and multiplicative seasonality give different pictures; if the swings grow with the level, take logs first.
rng = np.random.default_rng(2)
t = np.arange(120) # ten years, monthly
season = 10 * np.sin(2 * np.pi * t / 12)
y = pd.Series(0.5 * t + season + rng.normal(0, 3, 120))
trend = y.rolling(12, center=True).mean().rolling(2, center=True).mean() # centred 2x12 moving average
detr = y - trend
seasonal = detr.groupby(t % 12).transform('mean')
resid = y - trend - seasonal
amp = (seasonal.max() - seasonal.min()) / 2 # true amplitude is 10Assumes import numpy as np and import pandas as pd. Each snippet simulates or makes up its own series, as the comments say.
The same idea with a library
# Python — STL decomposition from statsmodels.tsa.seasonal import STL stl = STL(series, period=12, robust=True) result = stl.fit() result.plot() # result.trend, result.seasonal, result.resid
- R. B. Cleveland, W. S. Cleveland, J. E. McRae & I. Terpenning, “STL: A Seasonal-Trend Decomposition Procedure Based on Loess”, Journal of Official Statistics 6(1), 1990
- Forecasting: Principles and Practice (3rd ed.), R. J. Hyndman & G. Athanasopoulos, OTexts, 2021
Last reviewed October 2026 · How this site checks its content · Report a mistake