Анализ временных рядов в Python: от основ до продвинутых техник
Для кого эта статья:
- Аналитики данных и специалисты в области прогнозирования
- Студенты и начинающие разработчики, интересующиеся анализом данных
Профессионалы, работающие в области бизнеса и статистики, ищущие новые инструменты для анализа временных рядов
Анализ временных рядов — это ключ к раскрытию бизнес-трендов и прогнозированию будущих результатов. С использованием Python процесс становится не только доступным, но и значительно мощнее. 📊 Как аналитик, я не раз убеждался: правильно выбранные инструменты и методы могут превратить хаотичные временные данные в ценные инсайты, способные определить судьбу проекта. Давайте рассмотрим 5 мощнейших библиотек Python, которые изменят ваш подход к временным рядам, и разберем реальные примеры их применения для получения конкурентного преимущества.
Хотите не просто читать о возможностях Python для анализа данных, но и применять эти знания в реальных проектах? Курсы Обучение Python-разработке от Skypro — это идеальный баланс теории и практики. От базовых концепций до продвинутого анализа временных рядов, вы пройдете путь от новичка до профессионала, способного решать сложные аналитические задачи. Наши выпускники успешно трудоустраиваются уже через 6-9 месяцев обучения. Инвестируйте в навыки, которые останутся востребованными!
Python и временные ряды: ключевые понятия и типы анализа
Временные ряды — это последовательности точек данных, измеренных через определенные временные интервалы. Анализ временных рядов позволяет извлекать значимые статистические данные и другие характеристики, а также прогнозировать будущие значения на основе ранее наблюдаемых. 🕰️
Перед погружением в библиотеки, давайте разберемся с фундаментальными компонентами временных рядов:
- Тренд — долгосрочное направление движения данных (восходящее, нисходящее, стабильное)
- Сезонность — регулярные и предсказуемые изменения, повторяющиеся в фиксированных интервалах
- Цикличность — подъемы и спады, не имеющие фиксированной периодичности
- Нерегулярные колебания — непредсказуемые факторы, влияющие на данные
Основные типы анализа временных рядов в Python включают:
| Тип анализа | Применение | Популярные методы |
|---|---|---|
| Декомпозиция ряда | Разделение ряда на компоненты (тренд, сезонность, остатки) | Аддитивная и мультипликативная декомпозиция |
| Сглаживание | Устранение шума для выявления паттернов | Скользящее среднее, экспоненциальное сглаживание |
| Прогнозирование | Предсказание будущих значений | ARIMA, SARIMA, Prophet, машинное обучение |
| Анализ аномалий | Обнаружение необычных значений | Статистические тесты, изолирующие леса |
Михаил Петров, ведущий аналитик данных
Столкнувшись с задачей оптимизации цепочки поставок для крупного ритейлера, я обнаружил, что их методы прогнозирования были примитивны — обычные электронные таблицы и интуитивные оценки. Первое, что я сделал — выгрузил исторические данные по продажам и применил декомпозицию временного ряда с использованием Python.
Результаты были потрясающими: мы выявили сильную недельную сезонность, о которой компания даже не подозревала, а также годовой сезонный паттерн, который полностью опровергал их текущие методики прогнозирования. После внедрения модели на основе SARIMA, точность прогнозов увеличилась на 37%, что привело к сокращению запасов на складах на 22% без ущерба для наличия товаров. Клиент был ошеломлен — Python и правильный анализ временных рядов буквально трансформировали их бизнес за несколько месяцев.
Для успешного анализа временных рядов в Python критически важно понимать особенности работы с данными, привязанными к временным меткам:
- Стационарность — свойство ряда, при котором его статистические характеристики не меняются со временем
- Автокорреляция — корреляция между элементами ряда и теми же элементами с лагом
- Частотность — временной интервал между последовательными наблюдениями (ежедневно, ежечасно и т.д.)
- Пропущенные значения — требуют специальных методов обработки в контексте временных рядов
Теперь, когда мы заложили теоретический фундамент, давайте перейдем к библиотекам Python, которые превращают сложный анализ временных рядов в управляемый процесс.

Pandas и NumPy: фундамент для работы с временными данными
Pandas и NumPy образуют мощный тандем, являющийся основой для любого анализа временных рядов в Python. Pandas предоставляет специальные структуры данных и функции для эффективной работы с временными рядами, а NumPy обеспечивает вычислительную эффективность. 🐼
Начнем с базовых операций обработки временных рядов:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Создание временного ряда
dates = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')
values = np.random.randn(len(dates)).cumsum() # Случайный ряд с накоплением
time_series = pd.Series(values, index=dates)
# Базовые операции с временным рядом
print("Первые 5 значений ряда:")
print(time_series.head())
# Ресемплинг (изменение частоты временного ряда)
monthly_mean = time_series.resample('M').mean()
print("\nСреднемесячные значения:")
print(monthly_mean)
Pandas предлагает множество мощных функций для работы с временными данными:
- Сдвиги данных (Shifting) — перемещение значений вперед или назад для анализа лагов
- Скользящие окна (Rolling windows) — вычисление статистик на основе скользящих окон данных
- Агрегация по времени — группировка данных по различным временным интервалам
- Обработка пропущенных значений — методы интерполяции, учитывающие временной контекст
# Применение скользящего среднего
rolling_mean = time_series.rolling(window=7).mean() # 7-дневное скользящее среднее
# Сдвиг данных для анализа лагов
lagged = time_series.shift(periods=7) # Сдвиг на неделю вперед
# Визуализация исходного ряда и скользящего среднего
plt.figure(figsize=(12, 6))
plt.plot(time_series.index, time_series.values, label='Исходный ряд')
plt.plot(rolling_mean.index, rolling_mean.values, label='7-дневное скользящее среднее', color='red')
plt.legend()
plt.title('Временной ряд и его скользящее среднее')
plt.tight_layout()
Работа с сезонными данными и определение временных зависимостей — ещё одна сильная сторона Pandas:
# Создание временного ряда с сезонным паттерном
dates_seasonal = pd.date_range(start='2020-01-01', periods=730, freq='D')
seasonal_pattern = 10 + 5 * np.sin(np.arange(len(dates_seasonal)) * 2 * np.pi / 365)
noise = np.random.normal(0, 1, len(dates_seasonal))
seasonal_series = pd.Series(seasonal_pattern + noise, index=dates_seasonal)
# Выделение сезонности с помощью группировки по месяцам
monthly_avg = seasonal_series.groupby(seasonal_series.index.month).mean()
print("Средние значения по месяцам:")
print(monthly_avg)
| Функционал | Pandas | NumPy |
|---|---|---|
| Структуры данных для временных рядов | Series, DataFrame с DatetimeIndex | n-мерные массивы без привязки к датам |
| Работа с временными метками | Встроенная поддержка дат, времени, временных зон | Требует дополнительных манипуляций |
| Производительность | Оптимизирована для операций с временными рядами | Высокоэффективные числовые вычисления |
| Обработка пропусков | Встроенные методы (fillna, interpolate, etc.) | Базовые функции (np.nan, np.isnan) |
| Агрегации по времени | resample, rolling, expanding | Требует ручной реализации |
Важно помнить о некоторых нюансах при работе с Pandas для анализа временных рядов:
- При обработке больших объемов данных может возникнуть проблема с производительностью
- Локализация времени (timezone) может привести к неожиданным результатам, если не контролировать этот аспект
- Частые преобразования между типами данных Pandas и NumPy могут замедлить анализ
Pandas и NumPy предоставляют великолепную основу, но для более сложного анализа и прогнозирования нам понадобятся специализированные библиотеки, к которым мы переходим далее.
Statsmodels: статистический анализ и ARIMA-моделирование
Библиотека Statsmodels предоставляет надежные инструменты для статистического анализа временных рядов и построения прогностических моделей, включая знаменитые методы ARIMA (Autoregressive Integrated Moving Average) и их модификации. 📈
Начнем с базового анализа временного ряда с использованием Statsmodels:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.api as sm
from statsmodels.tsa.seasonal import seasonal_decompose
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
# Загрузка данных (для примера используем авиаперевозки)
air = sm.datasets.get_rdataset("AirPassengers", "datasets").data
air.index = pd.date_range(start='1949-01-01', periods=len(air), freq='M')
air_series = air['value']
# Декомпозиция временного ряда
decomposition = seasonal_decompose(air_series, model='multiplicative')
# Визуализация декомпозиции
fig = decomposition.plot()
plt.tight_layout()
Декомпозиция — это мощный инструмент, позволяющий разделить временной ряд на компоненты: тренд, сезонность и остатки. Это помогает лучше понять структуру данных перед моделированием.
Теперь перейдем к проверке стационарности — критически важному шагу перед построением ARIMA-моделей:
from statsmodels.tsa.stattools import adfuller
# Тест Дики-Фуллера на стационарность
def test_stationarity(timeseries):
# Проведение теста Дики-Фуллера
result = adfuller(timeseries, autolag='AIC')
print(f'ADF Statistic: {result[0]:.3f}')
print(f'p-value: {result[1]:.3f}')
print('Critical Values:')
for key, value in result[4].items():
print(f' {key}: {value:.3f}')
# Интерпретация результатов
if result[1] <= 0.05:
print("Ряд стационарен (отвергаем нулевую гипотезу)")
else:
print("Ряд нестационарен (не можем отвергнуть нулевую гипотезу)")
# Применение теста
test_stationarity(air_series)
# Для достижения стационарности часто применяют дифференцирование
air_diff = air_series.diff().dropna()
test_stationarity(air_diff)
После проверки стационарности и необходимых преобразований, мы готовы к построению ARIMA-модели:
from statsmodels.tsa.arima.model import ARIMA
# Определение параметров модели (p, d, q)
# p – порядок авторегрессии
# d – порядок интеграции (дифференцирования)
# q – порядок скользящего среднего
p, d, q = 1, 1, 1
# Создание и обучение модели ARIMA
model = ARIMA(air_series, order=(p, d, q))
results = model.fit()
print(results.summary())
# Прогнозирование будущих значений
forecast_steps = 12 # Прогноз на 12 месяцев вперед
forecast = results.forecast(steps=forecast_steps)
# Визуализация прогноза
plt.figure(figsize=(12, 6))
plt.plot(air_series, label='Исторические данные')
plt.plot(pd.date_range(start=air_series.index[-1], periods=forecast_steps+1, freq='M')[1:],
forecast, label='Прогноз', color='red')
plt.legend()
plt.title('Прогнозирование пассажиропотока с помощью ARIMA')
plt.tight_layout()
Анастасия Соколова, руководитель отдела аналитики
Помню, как начинала проект в финтех-компании, где задача стояла предсказать объем транзакций по кредитным картам для оптимизации мощностей процессинга. Первым шагом я проанализировала структуру имеющихся данных – 3 года ежедневных транзакций.
Применив декомпозицию временного ряда с помощью Statsmodels, мы обнаружили ярко выраженную недельную сезонность (пиковые значения в пятницу и выходные) и месячную (всплески в начале и конце месяца). Что интересно – годовая сезонность была не так выражена, как предполагали бизнес-заказчики!
Я попробовала несколько моделей, но SARIMA с параметрами (2,1,1)(1,1,1,7) показала наилучшие результаты, улавливая как долгосрочные тренды, так и недельные колебания. Это позволило сократить резервные мощности серверов на 18%, что в масштабе компании дало экономию около $400K в год. Без Statsmodels такой глубокий анализ потребовал бы намного больше времени и кастомного кода.
Для более сложных случаев с выраженной сезонностью, можно использовать SARIMA (Seasonal ARIMA):
from statsmodels.tsa.statespace.sarimax import SARIMAX
# Параметры для SARIMA(p,d,q)(P,D,Q,s)
# p, d, q – обычные параметры ARIMA
# P, D, Q – сезонные параметры
# s – длина сезонного цикла (12 для месячных данных с годовой сезонностью)
p, d, q = 1, 1, 1
P, D, Q, s = 1, 1, 1, 12
# Создание и обучение модели SARIMA
sarima_model = SARIMAX(air_series, order=(p, d, q),
seasonal_order=(P, D, Q, s))
sarima_results = sarima_model.fit()
print(sarima_results.summary())
# Прогнозирование с учетом сезонности
sarima_forecast = sarima_results.forecast(steps=forecast_steps)
Statsmodels также предлагает инструменты для диагностики моделей и выбора оптимальных параметров:
- Информационные критерии (AIC, BIC) для выбора лучшей модели
- Анализ остатков для проверки адекватности модели
- Автокорреляционная функция (ACF) и частная автокорреляционная функция (PACF) для определения параметров модели
- Перекрестная валидация по временным рядам для оценки точности прогнозирования
Statsmodels — мощный инструмент для классического статистического анализа временных рядов, но для некоторых сценариев могут потребоваться более современные и простые в использовании решения, такие как Prophet, который мы рассмотрим далее.
Prophet: инструмент Facebook для прогнозирования рядов
Prophet — это библиотека, разработанная для прогнозирования временных рядов, которая автоматически обнаруживает паттерны в данных и обеспечивает точные прогнозы с минимальным участием пользователя. Особенно эффективна для рядов с сильной сезонностью и нерегулярными выбросами. 📆
Основные преимущества Prophet:
- Простота использования — минимальное количество параметров для настройки
- Робастность — устойчивость к пропущенным данным и выбросам
- Масштабируемость — эффективная работа с большими объемами данных
- Интерпретируемость — прозрачность компонентов прогноза (тренд, сезонность, праздники)
Начнем с базового примера использования Prophet:
import pandas as pd
from prophet import Prophet
import matplotlib.pyplot as plt
# Подготовка данных в формате, необходимом для Prophet
# Prophet требует DataFrame с колонками 'ds' (даты) и 'y' (значения)
df = pd.DataFrame({
'ds': air_series.index,
'y': air_series.values
})
# Создание и обучение модели
model = Prophet()
model.fit(df)
# Создание фрейма для прогноза
future = model.make_future_dataframe(periods=12, freq='M')
# Прогнозирование
forecast = model.predict(future)
# Визуализация результатов
fig = model.plot(forecast)
plt.title('Прогноз пассажиропотока с помощью Prophet')
plt.tight_layout()
# Визуализация компонентов модели (тренд, сезонность, и т.д.)
fig2 = model.plot_components(forecast)
plt.tight_layout()
Prophet автоматически обнаруживает и моделирует различные компоненты временного ряда:
| Компонент | Описание | Параметры настройки |
|---|---|---|
| Тренд | Долгосрочная тенденция изменения данных | growth, changepointpriorscale |
| Годовая сезонность | Повторяющиеся годовые паттерны | yearly_seasonality |
| Недельная сезонность | Повторяющиеся недельные паттерны | weekly_seasonality |
| Дневная сезонность | Повторяющиеся суточные паттерны | daily_seasonality |
| Праздники/События | Влияние особых дней | holidays DataFrame |
Одна из сильных сторон Prophet — возможность учитывать влияние праздников и специальных событий:
# Создание DataFrame с праздниками
holidays = pd.DataFrame({
'holiday': 'thanksgiving',
'ds': pd.to_datetime(['2021-11-25', '2022-11-24', '2023-11-23']),
'lower_window': -1,
'upper_window': 1,
})
# Добавление рождественских праздников
christmas = pd.DataFrame({
'holiday': 'christmas',
'ds': pd.to_datetime(['2021-12-25', '2022-12-25', '2023-12-25']),
'lower_window': -1,
'upper_window': 1,
})
holidays = pd.concat([holidays, christmas])
# Создание модели с учетом праздников
model_with_holidays = Prophet(holidays=holidays)
model_with_holidays.fit(df)
# Прогнозирование
future = model_with_holidays.make_future_dataframe(periods=12, freq='M')
forecast_with_holidays = model_with_holidays.predict(future)
Prophet также предлагает возможности для тонкой настройки и дополнительной регуляризации модели:
# Модель с настраиваемыми параметрами
model_custom = Prophet(
changepoint_prior_scale=0.05, # Гибкость тренда
seasonality_prior_scale=10, # Сила сезонных компонентов
holidays_prior_scale=10, # Влияние праздников
seasonality_mode='multiplicative' # Режим сезонности
)
model_custom.fit(df)
# Добавление пользовательских сезонностей
model_custom.add_seasonality(
name='quarterly',
period=91.25,
fourier_order=8
)
Для оценки качества модели Prophet предоставляет инструменты кросс-валидации:
from prophet.diagnostics import cross_validation, performance_metrics
# Проведение кросс-валидации
df_cv = cross_validation(model, initial='730 days', period='180 days', horizon='365 days')
# Расчет метрик производительности
df_p = performance_metrics(df_cv)
print(df_p.head())
# Визуализация результатов кросс-валидации
from prophet.plot import plot_cross_validation_metric
fig = plot_cross_validation_metric(df_cv, metric='mape')
plt.title('Средняя абсолютная процентная ошибка (MAPE) по горизонту прогноза')
plt.tight_layout()
Хотя Prophet отлично справляется с большинством задач прогнозирования временных рядов, есть некоторые ограничения:
- Может быть менее гибким для очень нестандартных паттернов данных
- Не так эффективен для очень коротких временных рядов
- Иногда переоценивает влияние сезонности
В следующем разделе мы рассмотрим дополнительные библиотеки и инструменты, которые могут дополнить ваш арсенал для анализа временных рядов.
Дополнительные библиотеки и инструменты для продвинутой аналитики
Помимо уже рассмотренных библиотек, Python-экосистема предлагает множество специализированных инструментов для продвинутого анализа временных рядов. Эти библиотеки могут существенно расширить ваши аналитические возможности для решения специфических задач. 🚀
- pmdarima (auto_arima) — автоматически подбирает оптимальные параметры ARIMA-моделей
- TBATS — специализированная модель для данных с множественной сезонностью
- Sklearn — применение классических алгоритмов машинного обучения для временных рядов
- Neural Prophet — объединяет подход Prophet с нейронными сетями для более гибких моделей
- GluonTS — фреймворк для глубокого обучения на временных рядах
Рассмотрим применение pmdarima для автоматического подбора ARIMA-моделей:
import pmdarima as pm
# Автоматический подбор параметров ARIMA
auto_model = pm.auto_arima(
air_series,
seasonal=True, # Учет сезонности
m=12, # Длина сезонного цикла (12 месяцев)
d=None, # Автоматическое определение порядка интеграции
start_p=0, max_p=3, # Диапазон для параметра p
start_q=0, max_q=3, # Диапазон для параметра q
information_criterion='aic', # Критерий выбора модели
trace=True, # Вывод процесса подбора
error_action='ignore', # Игнорирование ошибок
stepwise=True # Пошаговый алгоритм поиска
)
print(auto_model.summary())
# Прогнозирование с помощью найденной модели
forecast, conf_int = auto_model.predict(n_periods=12, return_conf_int=True)
# Визуализация прогноза с доверительными интервалами
plt.figure(figsize=(12, 6))
plt.plot(air_series, label='Исторические данные')
forecast_index = pd.date_range(start=air_series.index[-1], periods=13, freq='M')[1:]
plt.plot(forecast_index, forecast, label='Прогноз', color='red')
plt.fill_between(forecast_index,
conf_int[:, 0], conf_int[:, 1],
color='red', alpha=0.2, label='95% доверительный интервал')
plt.legend()
plt.title('Прогноз с помощью auto_arima')
plt.tight_layout()
Применение алгоритмов машинного обучения из sklearn для прогнозирования:
from sklearn.ensemble import RandomForestRegressor
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
# Подготовка данных для машинного обучения
def create_features(df):
"""Создание признаков для временного ряда."""
df = df.copy()
df['month'] = df.index.month
df['day'] = df.index.day
df['day_of_week'] = df.index.dayofweek
df['quarter'] = df.index.quarter
return df
# Преобразование исходного ряда в DataFrame с признаками
air_df = pd.DataFrame(air_series)
air_df.columns = ['value']
features = create_features(air_df)
# Разделение на обучающую и тестовую выборки
train = features[:-12]
test = features[-12:]
# Масштабирование целевой переменной
scaler = MinMaxScaler()
train['value_scaled'] = scaler.fit_transform(train[['value']])
test['value_scaled'] = scaler.transform(test[['value']])
# Определение признаков и целевой переменной
FEATURES = ['month', 'day', 'day_of_week', 'quarter']
TARGET = 'value_scaled'
# Обучение модели Random Forest
model = RandomForestRegressor(n_estimators=100, random_state=42)
model.fit(train[FEATURES], train[TARGET])
# Прогнозирование
test['prediction_scaled'] = model.predict(test[FEATURES])
test['prediction'] = scaler.inverse_transform(test[['prediction_scaled']])
# Оценка точности
rmse = np.sqrt(mean_squared_error(test['value'], test['prediction']))
print(f'RMSE: {rmse:.2f}')
GluonTS предоставляет мощные инструменты для глубокого обучения на временных рядах:
# Пример использования GluonTS (требуется установка библиотеки)
# pip install gluonts
import mxnet as mx
from gluonts.dataset.common import ListDataset
from gluonts.dataset.field_names import FieldName
from gluonts.model.deepar import DeepAREstimator
from gluonts.trainer import Trainer
# Подготовка данных в формате GluonTS
start_date = pd.Timestamp("1949-01-01", freq="M")
train_data = ListDataset(
[
{
FieldName.TARGET: air_series.values,
FieldName.START: start_date
}
],
freq="M"
)
# Создание и обучение модели DeepAR
estimator = DeepAREstimator(
freq="M",
prediction_length=12,
context_length=24,
trainer=Trainer(
epochs=50,
ctx=mx.cpu()
)
)
predictor = estimator.train(train_data)
Для обнаружения аномалий в временных рядах можно использовать библиотеку PyOD:
from pyod.models.iforest import IForest
import numpy as np
# Подготовка данных для обнаружения аномалий
X = air_series.values.reshape(-1, 1)
# Создание и обучение модели изолирующего леса
clf = IForest(contamination=0.05) # Предполагаем, что 5% наблюдений – аномалии
clf.fit(X)
# Прогнозирование аномалий
anomaly_scores = clf.decision_scores_
anomaly_labels = clf.predict(X)
# Визуализация аномалий
plt.figure(figsize=(12, 6))
plt.plot(air_series.index, air_series.values, label='Данные')
plt.scatter(air_series.index[anomaly_labels==1],
air_series.values[anomaly_labels==1],
color='red', label='Аномалии')
plt.legend()
plt.title('Обнаружение аномалий в временном ряде')
plt.tight_layout()
При выборе библиотеки для продвинутой аналитики временных рядов, учитывайте следующие факторы:
- Объем и характеристики данных — некоторые библиотеки лучше работают с большими объемами данных
- Требуемая точность — для критичных задач может потребоваться ансамбль моделей
- Интерпретируемость — некоторые модели (например, Prophet) предоставляют понятные компоненты прогноза
- Вычислительные ресурсы — модели глубокого обучения требуют значительных вычислительных мощностей
- Время обучения — для некоторых задач может быть критичным быстрое обучение и переобучение моделей
Выбор правильной библиотеки и метода анализа зависит от конкретной задачи и характеристик ваших данных. Часто наилучший результат достигается комбинированием различных подходов и инструментов.
Анализ временных рядов с использованием Python — это мощный навык, открывающий огромные возможности для извлечения ценных инсайтов из данных. Начав с фундаментальных инструментов Pandas и NumPy, вы можете постепенно расширять свой арсенал, добавляя статистические модели из Statsmodels, интуитивно понятные прогнозы с Prophet и продвинутые методики с использованием машинного обучения и глубоких нейронных сетей. Главное — подбирать инструменты под конкретную задачу и данные, а не пытаться применить один универсальный метод ко всем ситуациям. Именно это отличает профессионального аналитика от новичка. Не бойтесь экспериментировать и комбинировать различные подходы для достижения наилучших результатов.