Декомпозиция временного ряда: тренд, сезонность, шум

Что такое декомпозиция

Decomposition (декомпозиция) временного ряда — разложение на компоненты:

  • Trend (тренд). Долгосрочное направление роста или падения.
  • Seasonality (сезонность). Регулярные периодические колебания.
  • Cycle. Долгосрочные waves, не fixed period (экономические циклы).
  • Residual (остаток). То, что не объясняется trend и seasonality.

Разложение помогает понять behavior данных, выбрать forecasting model, выявить аномалии.

Additive vs Multiplicative

Две модели комбинирования компонентов.

Additive. Компоненты суммируются.

Y(t) = Trend(t) + Seasonal(t) + Residual(t)

Применима когда amplitude seasonality constant over time. Seasonal swings одинаковые при любом уровне тренда.

Multiplicative. Компоненты множатся.

Y(t) = Trend(t) × Seasonal(t) × Residual(t)

Применима когда amplitude seasonality пропорциональна уровню. С ростом тренда seasonal swings тоже растут.

Для multiplicative часто используют log-transform, после которого multiplicative становится additive:

log(Y) = log(Trend) + log(Seasonal) + log(Residual)

Как отличить

Визуально смотрите на seasonal amplitudes.

Additive signals.

  • Температура по месяцам: зима-лето разница всегда ~30°C.
  • Simple business metrics со стабильной seasonality.

Multiplicative signals.

  • Продажи e-commerce: дneсs growth + bigger spike on Black Friday.
  • Revenue с растущим бизнесом и Q4 seasonality.

Тест: разделите ряд на 2-3 сегмента, посмотрите amplitude seasonality в каждом. Растёт вместе с уровнем → multiplicative. Constant → additive.

Классическая decomposition в Python

import pandas as pd
from statsmodels.tsa.seasonal import seasonal_decompose

# Assuming monthly data
result = seasonal_decompose(y, model='additive', period=12)

result.plot()
plt.show()

trend = result.trend
seasonal = result.seasonal
residual = result.resid

Для multiplicative — model='multiplicative'.

Классический метод использует moving averages для оценки trend, потом averages по сезону для seasonal, оставшееся — residual.

Простой, но с недостатками:

  • Первые/последние периоды теряются (MA window).
  • Smooth trend может over-smooth.
  • Одинаковый seasonal pattern для всех лет.

STL decomposition

Seasonal-Trend decomposition using LOESS (STL) — современный метод. Преимущества:

  • Robust к outliers.
  • Гибкий seasonal pattern — может меняться во времени.
  • Работает с любым seasonal period.
  • Нет lost periods на границах.
from statsmodels.tsa.seasonal import STL

stl = STL(y, period=12, robust=True)
result = stl.fit()

result.plot()

Параметры:

  • period — seasonal cycle length.
  • seasonal — smoothness of seasonal component.
  • trend — smoothness of trend.
  • robust — использовать weights для outliers.

STL — go-to метод для современной decomposition.

X-13ARIMA-SEATS

Метод от U.S. Census Bureau. Самый advanced для economic data:

  • Автоматическое выявление outliers.
  • Handling trading day effects (понедельник vs суббота).
  • Holiday adjustments (Easter, Christmas).
  • Calendar effects.

Используется в официальной статистике (GDP, unemployment).

from statsmodels.tsa.x13 import x13_arima_analysis
result = x13_arima_analysis(y)
# Требует X13 binary installed

Для бизнес-данных обычно overkill, но для макростат — стандарт.

Multiple seasonality

Реальность часто имеет multiple seasonal patterns.

Daily traffic:

  • Weekly (пн-пт vs сб-вс)
  • Yearly (летний спад)
  • Holiday effects

STL handles только одну seasonality. Для multiple:

MSTL. Multiple STL. Библиотека statsforecast.

from statsforecast.models import MSTL

mstl = MSTL(season_length=[7, 365.25])
mstl.fit(y)

Prophet. Facebook library. Автоматически handles multiple seasonalities.

TBATS. Complex seasonal ARIMA variant. Handles non-integer seasonality (365.25 дней в year).

Применение в бизнесе

Forecasting. Раздельное моделирование trend и seasonality → точнее прогнозы.

Forecast = Extrapolated Trend + Seasonal (from same month in past)

Anomaly detection. После удаления trend и seasonality остаются residuals. Большие residuals — аномалии.

# Z-score на residuals
z = (residuals - residuals.mean()) / residuals.std()
anomalies = df[abs(z) > 3]

Seasonally adjusted metrics. Убираем seasonal effect для понимания истинного growth.

Y_sa = Y - Seasonal   # additive
Y_sa = Y / Seasonal   # multiplicative

Seasonally adjusted revenue показывает underlying growth без шума от Q4 peak.

Identifying changes. Комendcreased trend slope может signal business model change. Новая seasonal pattern — signal customer behavior shift.

Timе series analysis — частая тема на собесах analytics и data science. В тренажёре Карьерник есть задачи на forecasting, сезонность и аналитику временных рядов.

Step-by-step example

Данные: daily revenue e-commerce store за 3 года.

Шаг 1. Visualize.

df['revenue'].plot()
# Видим: растущий тренд, недельная сезонность (weekends > weekdays),
# годовая сезонность (Q4 spike)

Шаг 2. STL decomposition.

from statsforecast.models import MSTL

mstl = MSTL(season_length=[7, 365])
mstl.fit(df['revenue'].values)
components = mstl.predict(h=30)  # или получить fitted values

Шаг 3. Analyze trend.

# Trend показывает underlying growth rate
# Если linear: growth = coefficient per day
# Если shape меняется: business model changed at inflection point

Шаг 4. Analyze seasonality.

# Weekly: Tue-Wed могут быть low points, weekends peak
# Yearly: Black Friday, Christmas spikes
# Understand когда allocate marketing, staffing

Шаг 5. Forecast.

# Extrapolate trend + apply seasonal pattern
# Or use Prophet/SARIMA/ETS со встроенной декомпозицией

Filters для trend extraction

Alternative methods:

Hodrick-Prescott (HP) filter. Popular in economics. Разделяет trend и cyclical components.

from statsmodels.tsa.filters.hp_filter import hpfilter
cycle, trend = hpfilter(y, lamb=1600)  # lambda=1600 for quarterly

Baxter-King filter. Band-pass filter. Изолирует specific frequency ranges.

Kalman filter. Dynamic approach, handles complex state space models.

Для most business applications STL или seasonal_decompose — достаточно.

Handling missing data

Decomposition sensitive к пропускам. Опции:

Imputation перед decomposition:

  • Linear interpolation.
  • Seasonal interpolation (use same month/day в предыдущие years).

Decomposition с пропусками:

  • Prophet handles natively.
  • State space models (SARIMA, Kalman filter).

Избегайте FFill/BFill — создаёт artificial flat periods, искажает trend и seasonality.

Seasonality strength metric

Иногда нужно numerically assess, насколько seasonal ряд.

Seasonal strength = max(0, 1 - Var(Residual) / Var(Residual + Seasonal))

От 0 (no seasonality) до 1 (pure seasonal).

ss = max(0, 1 - np.var(residual) / np.var(residual + seasonal))

Помогает решить: stoит ли seasonal modeling, или white noise approach OK.

Типичные ошибки

Wrong seasonal period. Daily data с 30 period (monthly) → искаженная seasonality. Период должен совпадать с true cycle.

Additive для multiplicative data. Residuals будут гетероскедастичны. Визуально проверять.

Over-smoothing trend. Слишком wide LOESS window → trend «проглатывает» cycles.

Ignoring holidays. Easter, Chinese New Year, Ramadan — moveable dates. Standard decomposition их пропускает. Prophet handles.

Too short series. STL нуждается в 2+ полных seasonal cycles. Короткий ряд → unreliable.

Читайте также

FAQ

Какой метод decomposition лучший?

STL — хороший default. Prophet/MSTL для multiple seasonalities. X-13 для macro data.

Можно ли decompose короткий ряд?

< 2 полных cycles — результат unreliable. Лучше accumulate данные.

Multiplicative или additive — автоматически?

Автоматической детекции нет. Визуальный анализ amplitude. Rule: log-transform и decompose additively — safe option.

Decomposition = forecasting?

Нет. Decomposition — описательный analysis. Forecasting — extrapolating компоненты. Похожие but different tasks.