Анализ временных рядов в Python: от основ до продвинутых техник

Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • Аналитики данных и специалисты в области прогнозирования
  • Студенты и начинающие разработчики, интересующиеся анализом данных
  • Профессионалы, работающие в области бизнеса и статистики, ищущие новые инструменты для анализа временных рядов

    Анализ временных рядов — это ключ к раскрытию бизнес-трендов и прогнозированию будущих результатов. С использованием 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 обеспечивает вычислительную эффективность. 🐼

Начнем с базовых операций обработки временных рядов:

Python
Скопировать код
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) — вычисление статистик на основе скользящих окон данных
  • Агрегация по времени — группировка данных по различным временным интервалам
  • Обработка пропущенных значений — методы интерполяции, учитывающие временной контекст
Python
Скопировать код
# Применение скользящего среднего
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:

Python
Скопировать код
# Создание временного ряда с сезонным паттерном
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:

Python
Скопировать код
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-моделей:

Python
Скопировать код
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-модели:

Python
Скопировать код
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):

Python
Скопировать код
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:

Python
Скопировать код
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 — возможность учитывать влияние праздников и специальных событий:

Python
Скопировать код
# Создание 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 также предлагает возможности для тонкой настройки и дополнительной регуляризации модели:

Python
Скопировать код
# Модель с настраиваемыми параметрами
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 предоставляет инструменты кросс-валидации:

Python
Скопировать код
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-экосистема предлагает множество специализированных инструментов для продвинутого анализа временных рядов. Эти библиотеки могут существенно расширить ваши аналитические возможности для решения специфических задач. 🚀

  1. pmdarima (auto_arima) — автоматически подбирает оптимальные параметры ARIMA-моделей
  2. TBATS — специализированная модель для данных с множественной сезонностью
  3. Sklearn — применение классических алгоритмов машинного обучения для временных рядов
  4. Neural Prophet — объединяет подход Prophet с нейронными сетями для более гибких моделей
  5. GluonTS — фреймворк для глубокого обучения на временных рядах

Рассмотрим применение pmdarima для автоматического подбора ARIMA-моделей:

Python
Скопировать код
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 для прогнозирования:

Python
Скопировать код
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 предоставляет мощные инструменты для глубокого обучения на временных рядах:

Python
Скопировать код
# Пример использования 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:

Python
Скопировать код
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 и продвинутые методики с использованием машинного обучения и глубоких нейронных сетей. Главное — подбирать инструменты под конкретную задачу и данные, а не пытаться применить один универсальный метод ко всем ситуациям. Именно это отличает профессионального аналитика от новичка. Не бойтесь экспериментировать и комбинировать различные подходы для достижения наилучших результатов.

Загрузка...