← Назад к вопросам
Как анализировать временной ряд: тренд, сезонность, шум?
2.3 Middle🔥 171 комментариев
#Временные ряды
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Анализ временных рядов: компоненты и методы
Временной ряд (time series) — это последовательность наблюдений, упорядоченная по времени. Классический подход предполагает разложение ряда на три основные компоненты: тренд, сезонность и шум. Понимание этих компонент критично для прогнозирования и анализа.
Математическое представление
Y(t) = Trend(t) + Seasonality(t) + Noise(t)
Или в мультипликативной форме (когда компоненты зависят друг от друга):
Y(t) = Trend(t) * Seasonality(t) * Noise(t)
1. Тренд (Trend)
Тренд — это долгосрочное движение временного ряда вверх или вниз.
Визуализация и выявление тренда
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
# Сгенерировать данные с трендом
date_range = pd.date_range('2020-01-01', periods=365)
y = 10 + 0.1 * np.arange(365) + np.random.normal(0, 2, 365)
ts = pd.Series(y, index=date_range)
# Визуализировать
plt.figure(figsize=(12, 4))
plt.plot(ts.index, ts.values, label='Исходный ряд')
plt.title('Временной ряд с трендом')
plt.legend()
plt.show()
Методы выделения тренда
Метод скользящего среднего (Moving Average)
# Простое скользящее среднее
trend_ma = ts.rolling(window=30).mean()
plt.plot(ts.index, ts.values, label='Исходный ряд')
plt.plot(ts.index, trend_ma, label='Тренд (MA=30)', color='red')
plt.legend()
plt.show()
Метод экспоненциального сглаживания
from scipy.ndimage import uniform_filter1d
alpha = 0.3
trend_exp = ts.ewm(span=30, adjust=False).mean()
Полиномиальная регрессия
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
X = np.arange(len(ts)).reshape(-1, 1)
poly = PolynomialFeatures(degree=2)
X_poly = poly.fit_transform(X)
model = LinearRegression()
model.fit(X_poly, ts.values)
trend_poly = model.predict(X_poly)
2. Сезонность (Seasonality)
Сезонность — это повторяющийся паттерн через регулярные интервалы (суток, недель, месяцев).
Выявление периода сезонности
Метод автокорреляции (ACF)
from statsmodels.graphics.tsaplots import plot_acf
from statsmodels.tsa.stattools import adfuller
fig, ax = plt.subplots(figsize=(12, 4))
plot_acf(ts.dropna(), lags=100, ax=ax)
plt.title('Автокорреляция (ACF)')
plt.show()
Анализ Фурье (FFT)
from scipy.fft import fft
fft_values = np.abs(fft(ts.dropna()))
frequencies = np.fft.fftfreq(len(ts))
top_freq_idx = np.argsort(fft_values)[-5:]
print(f'Периоды сезонности: {1 / frequencies[top_freq_idx]}')
Разложение (Decomposition)
from statsmodels.tsa.seasonal import seasonal_decompose
decomposition = seasonal_decompose(ts, model='additive', period=30)
trend = decomposition.trend
seasonal = decomposition.seasonal
residual = decomposition.resid
fig, axes = plt.subplots(4, 1, figsize=(12, 10))
axes[0].plot(ts)
axes[0].set_ylabel('Исходный ряд')
axes[1].plot(trend)
axes[1].set_ylabel('Тренд')
axes[2].plot(seasonal)
axes[2].set_ylabel('Сезонность')
axes[3].plot(residual)
axes[3].set_ylabel('Шум')
plt.tight_layout()
plt.show()
3. Шум (Noise)
Шум — это случайная компонента, которая остаётся после удаления тренда и сезонности.
Анализ шума
residuals = decomposition.resid.dropna()
from statsmodels.tsa.stattools import adfuller
adf_result = adfuller(residuals)
print(f'ADF статистика: {adf_result[0]}')
print(f'p-value: {adf_result[1]}')
if adf_result[1] < 0.05:
print('Ряд стационарен')
else:
print('Ряд нестационарен')
plt.hist(residuals, bins=30, edgecolor='black')
plt.title('Распределение шума')
plt.xlabel('Значение')
plt.ylabel('Частота')
plt.show()
Полный пример анализа
import pandas as pd
import numpy as np
from statsmodels.tsa.seasonal import seasonal_decompose
import matplotlib.pyplot as plt
df = pd.read_csv('stock_prices.csv', parse_dates=['date'], index_col='date')
ts = df['close']
decomposition = seasonal_decompose(ts, model='multiplicative', period=252)
trend = decomposition.trend
seasonal = decomposition.seasonal
residual = decomposition.resid
print(f'Тренд: минимум={trend.min():.2f}, максимум={trend.max():.2f}')
print(f'Сезонность: амплитуда={seasonal.max() - seasonal.min():.4f}')
print(f'Шум: std={residual.std():.4f}')
fig, axes = plt.subplots(4, 1, figsize=(14, 10))
axes[0].plot(ts.index, ts.values)
axes[0].set_title('Исходный ряд')
axes[1].plot(trend.index, trend.values)
axes[1].set_title('Тренд')
axes[2].plot(seasonal.index, seasonal.values)
axes[2].set_title('Сезонность')
axes[3].plot(residual.index, residual.values)
axes[3].set_title('Шум')
plt.tight_layout()
plt.show()
Выводы
- Тренд определяет долгосрочное направление через скользящее среднее или полиномиальную регрессию
- Сезонность выявляется через ACF, FFT или автоматическое разложение
- Шум анализируется проверкой стационарности и его распределением
- Разложение — ключевой инструмент для понимания структуры временного ряда перед прогнозированием