Добро пожаловать во вторую часть нашей серии статей «Работа с временными рядами в Python.» В первой части, мы ознакомились с основами работы с временными рядами и научились анализировать и визуализировать их. Теперь мы переходим к более продвинутым аспектам этой увлекательной темы.
В этой статье мы сосредоточимся на прогнозировании временных рядов, что имеет огромное значение в множестве областей, включая экономику, финансы и даже погоду. Это открывает новые возможности для анализа различных типов временных данных.
Прогнозирование погоды
Прогнозирование погоды — это еще одна важная область, где анализ временных рядов играет важную роль. Рассмотрим пример прогнозирования температуры.
Создание Dataset
Для примера создадим dataset с данными о средней дневной температуре в течение нескольких лет.
# Создаем даты с января 2020 года по декабрь 2022 года dates = pd.date_range(start='2020-01-01', end='2022-12-31', freq='D') # Генерируем случайные значения температуры temperature = np.random.normal(loc=25, scale=5, size=len(dates)) # Создаем DataFrame temperature_df = pd.DataFrame({'Дата': dates, 'Температура': temperature}) # Устанавливаем 'Дата' в качестве индекса temperature_df.set_index('Дата', inplace=True) # Выводим первые несколько строк print(temperature_df.head())
Результат:
Температура Дата 2020-01-01 28.070296 2020-01-02 22.618478 2020-01-03 37.671305 2020-01-04 24.559199 2020-01-05 21.579757
Визуализация данных
Визуализируем данные о температуре, чтобы понять их динамику.
# Построим график температуры plt.figure(figsize=(12, 6)) plt.plot(temperature_df.index, temperature_df['Температура'], linestyle='-') plt.title('Средняя дневная температура') plt.xlabel('Дата') plt.ylabel('Температура (°C)') plt.grid(True) plt.show()

Выбор и обучение модели
Для прогнозирования погоды можно использовать различные модели, включая модели временных рядов и модели машинного обучения. Мы будем использовать модель SARIMA.
from statsmodels.tsa.statespace.sarimax import SARIMAX # Обучение модели SARIMA model = SARIMAX(temperature_df['Температура'], order=(1, 1, 1), seasonal_order=(1, 1, 1, 7)) model_fit = model.fit() # Вывод статистики модели print(model_fit.summary())
Результат:
SARIMAX Results ========================================================================================= Dep. Variable: Температура No. Observations: 1096 Model: SARIMAX(1, 1, 1)x(1, 1, 1, 7) Log Likelihood -3302.692 Date: Mon, 18 Sep 2023 AIC 6615.384 Time: 12:26:34 BIC 6640.344 Sample: 01-01-2020 HQIC 6624.832 - 12-31-2022 Covariance Type: opg ============================================================================== coef std err z P>|z| [0.025 0.975] ------------------------------------------------------------------------------ ar.L1 0.0297 0.033 0.899 0.368 -0.035 0.094 ma.L1 -0.9926 0.005 -182.224 0.000 -1.003 -0.982 ar.S.L7 0.0148 0.033 0.446 0.655 -0.050 0.080 ma.S.L7 -0.9862 0.012 -79.419 0.000 -1.011 -0.962 sigma2 24.5744 1.054 23.311 0.000 22.508 26.641 =================================================================================== Ljung-Box (L1) (Q): 0.00 Jarque-Bera (JB): 0.36 Prob(Q): 0.97 Prob(JB): 0.84 Heteroskedasticity (H): 0.96 Skew: 0.04 Prob(H) (two-sided): 0.69 Kurtosis: 3.05 ===================================================================================
Оценка качества прогноза
Оценка качества прогноза температуры может включать в себя сравнение прогнозных значений с фактическими данными и использование метрик, таких как MSE и MAE.
# Импортируем необходимую функцию from sklearn.metrics import mean_squared_error, mean_absolute_error # Прогноз на основе обученной модели forecast = model_fit.forecast(steps=7) # Рассчитываем MSE и MAE mse = mean_squared_error(temperature_df['Температура'][-7:], forecast) mae = mean_absolute_error(temperature_df['Температура'][-7:], forecast) print(f'MSE: {mse}') print(f'MAE: {mae}')
Результат:
MSE: 10.43521389383251 MAE: 2.4818868765063735
Прогноз на будущее
Теперь мы можем использовать обученную модель для прогнозирования температуры на следующие 7 дней.
# Прогноз на будущее (следующие 7 дней) forecast_future = model_fit.get_forecast(steps=7) # Создаем новый DataFrame для будущих значений future_dates = pd.date_range(start='2022-12-31', periods=7, freq='D') + pd.DateOffset(days=1) forecast_df = pd.DataFrame({'Дата': future_dates, 'Прогноз температуры': forecast_future.predicted_mean}) # Присоединяем прогноз к исходному DataFrame temperature_df = temperature_df.append(forecast_df) # Визуализация исходных данных и прогноза plt.figure(figsize=(12, 6)) plt.plot(temperature_df.index[:-7], temperature_df['Температура'][:-7], label='Исходные данные') plt.plot(temperature_df.index[-7:], temperature_df['Прогноз температуры'][-7:], label='Прогноз') plt.title('Прогноз средней дневной температуры') plt.xlabel('Дата') plt.ylabel('Температура (°C)') plt.legend() plt.grid(True) plt.show()

Прогнозирование трафика на веб-сайте
Рассмотрим пример прогнозирования количества посетителей на веб-сайте.
Создание Dataset
Для примера создадим dataset с данными о ежедневном трафике на веб-сайте.
import pandas as pd import numpy as np import matplotlib.pyplot as plt # Создаем условные даты dates = pd.date_range(start='2020-01-01', end='2022-12-31', freq='D') # Генерируем случайное количество посетителей traffic = np.random.randint(1000, 5000, size=len(dates)) # Создаем DataFrame traffic_df = pd.DataFrame({'Дата': dates, 'Посетители': traffic}) # Устанавливаем 'Дата' в качестве индекса traffic_df.set_index('Дата', inplace=True) # Выводим первые несколько строк print(traffic_df.head())
Результат:
Посетители Дата 2020-01-01 3776 2020-01-02 3641 2020-01-03 4092 2020-01-04 2057 2020-01-05 1936
Визуализация данных
Визуализируем данные о трафике на веб-сайте, чтобы увидеть их динамику.
# Построим график трафика plt.figure(figsize=(12, 6)) plt.plot(traffic_df.index, traffic_df['Посетители'], linestyle='-') plt.title('Трафик на веб-сайте') plt.xlabel('Дата') plt.ylabel('Посетители') plt.grid(True) plt.show()

Выбор и обучение модели
Для прогнозирования трафика на веб-сайте можно использовать различные модели, включая модели временных рядов и модели машинного обучения. Мы будем использовать модель ARIMA.
from statsmodels.tsa.arima.model import ARIMA # Обучение модели ARIMA model = ARIMA(traffic_df['Посетители'], order=(1, 1, 1)) model_fit = model.fit() # Вывод статистики модели print(model_fit.summary())
Результат:
SARIMAX Results ============================================================================== Dep. Variable: Посетители No. Observations: 1096 Model: ARIMA(1, 1, 1) Log Likelihood -9283.888 Date: Mon, 18 Sep 2023 AIC 18573.776 Time: 12:36:37 BIC 18588.771 Sample: 01-01-2020 HQIC 18579.450 - 12-31-2022 Covariance Type: opg ============================================================================== coef std err z P>|z| [0.025 0.975] ------------------------------------------------------------------------------ ar.L1 -0.0158 0.030 -0.524 0.601 -0.075 0.043 ma.L1 -1.0000 0.067 -14.838 0.000 -1.132 -0.868 sigma2 1.346e+06 5e-08 2.69e+13 0.000 1.35e+06 1.35e+06 =================================================================================== Ljung-Box (L1) (Q): 0.00 Jarque-Bera (JB): 65.30 Prob(Q): 0.97 Prob(JB): 0.00 Heteroskedasticity (H): 0.99 Skew: -0.02 Prob(H) (two-sided): 0.94 Kurtosis: 1.80 ===================================================================================
Оценка качества прогноза
Оценка качества прогноза трафика может включать в себя сравнение прогнозных значений с фактическими данными и использование метрик, таких как MSE и MAE.
# Прогноз на основе обученной модели forecast = model_fit.forecast(steps=7) # Рассчитываем MSE и MAE mse = mean_squared_error(traffic_df['Посетители'][-7:], forecast) mae = mean_absolute_error(traffic_df['Посетители'][-7:], forecast) print(f'MSE: {mse}') print(f'MAE: {mae}')
Результат:
MSE: 836944.4441271863 MAE: 818.829661603483
Продвинутые техники анализа временных рядов
Анализ временных рядов может стать более сложным, когда у вас есть дело с временными рядами, имеющими переменные интервалы между наблюдениями, сеточными данными или совместными временными рядами.
Временные ряды с переменными интервалами
В большинстве анализов временных рядов предполагается, что наблюдения происходят с постоянным интервалом времени. Однако в реальном мире данные могут иметь переменные интервалы между наблюдениями. Временные ряды с переменными интервалами могут возникать, например, в медицинских исследованиях, где пациенты по разному записывают свои показатели.
Создадим временной ряд с переменными интервалами, представляющий количество продаж в условном филиале МВидео.
import pandas as pd import numpy as np # Создаем dataset с переменными интервалами sales_data = {'Дата': pd.to_datetime(['2023-01-01', '2023-01-03', '2023-01-05', '2023-01-10']), 'Продажи': [100, 150, 80, 200]} sales_df = pd.DataFrame(sales_data) # Устанавливаем 'Дата' в качестве индекса sales_df.set_index('Дата', inplace=True)
Теперь у нас есть временной ряд с переменными интервалами. Как анализировать такие данные? Мы можем использовать методы интерполяции для заполнения промежутков между наблюдениями и сделать их более регулярными.
# Пересемплирование данных для установки регулярного интервала sales_df_resampled = sales_df.resample('D').asfreq() # Заполнение пропущенных значений интерполяцией sales_df_interpolated = sales_df_resampled.interpolate(method='linear') # Вывод интерполированных данных print(sales_df_interpolated)
Результат:
SARIMAX Results ============================================================================== Dep. Variable: Посетители No. Observations: 1096 Model: ARIMA(1, 1, 1) Log Likelihood -9283.888 Date: Mon, 18 Sep 2023 AIC 18573.776 Time: 12:36:37 BIC 18588.771 Sample: 01-01-2020 HQIC 18579.450 - 12-31-2022 Covariance Type: opg ============================================================================== coef std err z P>|z| [0.025 0.975] ------------------------------------------------------------------------------ ar.L1 -0.0158 0.030 -0.524 0.601 -0.075 0.043 ma.L1 -1.0000 0.067 -14.838 0.000 -1.132 -0.868 sigma2 1.346e+06 5e-08 2.69e+13 0.000 1.35e+06 1.35e+06 =================================================================================== Ljung-Box (L1) (Q): 0.00 Jarque-Bera (JB): 65.30 Prob(Q): 0.97 Prob(JB): 0.00 Heteroskedasticity (H): 0.99 Skew: -0.02 Prob(H) (two-sided): 0.94 Kurtosis: 1.80 ===================================================================================
Сеточный анализ временных рядов
Сеточный анализ временных рядов — это метод анализа, который позволяет исследовать несколько временных рядов, имеющих различные характеристики, в одном и том же контексте. Это особенно полезно, когда у вас есть набор данных, представляющий несколько компонентов или категорий продуктов в магазине, и вы хотите исследовать их динамику во времени.
Предположим, у нас есть данные о продажах разных категорий продуктов в магазине МВидео на протяжении нескольких месяцев. Категории продуктов могут включать в себя телевизоры, ноутбуки, смартфоны и бытовую технику.
import pandas as pd import numpy as np # Создаем dataset с продажами разных категорий продуктов data = {'Дата': pd.date_range(start='2023-01-01', periods=12, freq='M'), 'Продажи телевизоров': [50, 45, 55, 60, 70, 80, 90, 85, 75, 70, 60, 55], 'Продажи ноутбуков': [30, 35, 40, 45, 50, 60, 65, 70, 75, 80, 85, 90], 'Продажи смартфонов': [70, 75, 80, 85, 90, 95, 100, 105, 110, 115, 120, 125], 'Продажи бытовой техники': [40, 42, 45, 48, 50, 52, 55, 58, 60, 62, 65, 68]} sales_df = pd.DataFrame(data) # Устанавливаем 'Дата' в качестве индекса sales_df.set_index('Дата', inplace=True)
Теперь у нас есть данные о продажах четырех разных категорий продуктов в магазине МВидео. Проведем сеточный анализ для исследования динамики продаж.
1. Визуализация данных:
Сначала мы можем визуализировать продажи каждой категории продуктов на одном графике, чтобы увидеть их динамику во времени.
import matplotlib.pyplot as plt # Визуализация продаж каждой категории продуктов plt.figure(figsize=(12, 6)) for column in sales_df.columns: plt.plot(sales_df.index, sales_df[column], label=column) plt.title('Динамика продаж разных категорий продуктов') plt.xlabel('Дата') plt.ylabel('Продажи') plt.legend() plt.grid(True) plt.show()

2. Вычисление корреляций:
Для сеточного анализа мы также можем вычислить корреляции между продажами разных категорий продуктов. Это может помочь нам определить, есть ли взаимосвязь между продажами разных продуктов.
# Вычисление корреляций между продажами correlation_matrix = sales_df.corr() # Визуализация корреляционной матрицы import seaborn as sns plt.figure(figsize=(8, 6)) sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', linewidths=0.5) plt.title('Корреляционная матрица продаж') plt.show()

Визуализация корреляционной матрицы позволяет нам видеть, есть ли сильные связи между категориями продуктов.
3. Сравнение трендов:
Сеточный анализ также может включать в себя сравнение трендов продаж разных категорий продуктов. Мы можем использовать скользящее среднее для сглаживания данных и выявления трендов.
# Сглаживание данных с помощью скользящего среднего window = 3 # Размер окна скользящего среднего smoothed_sales_df = sales_df.rolling(window=window).mean() # Визуализация сглаженных данных plt.figure(figsize=(12, 6)) for column in smoothed_sales_df.columns: plt.plot(smoothed_sales_df.index, smoothed_sales_df[column], label=column) plt.title(f'Сглаженные продажи с окном {window}') plt.xlabel('Дата') plt.ylabel('Продажи') plt.legend() plt.grid(True) plt.show()

Сглаженные данные могут помочь нам более четко увидеть общие тренды продаж.
Сеточный анализ временных рядов может быть мощным инструментом для исследования динамики разных компонентов данных и выявления взаимосвязей между ними. Важно выбирать подходящие методы в зависимости от конкретной задачи и данных, с которыми вы работаете.
Совместные временные ряды
Совместные временные ряды — это анализ нескольких временных рядов, чтобы определить, существует ли между ними взаимосвязь или зависимость. Это может быть полезно, например, для выявления корреляций между продажами разных продуктов в магазине или между разными параметрами в медицинских исследованиях.
Создадим два временных ряда, представляющих продажи телевизоров и продажи ноутбуков в магазине МВидео, и определим, есть ли между ними корреляция.
import pandas as pd import numpy as np # Создаем dataset с продажами телевизоров и ноутбуков data = {'Дата': pd.date_range(start='2023-01-01', periods=12, freq='M'), 'Продажи телевизоров': [50, 45, 55, 60, 70, 80, 90, 85, 75, 70, 60, 55], 'Продажи ноутбуков': [30, 35, 40, 45, 50, 60, 65, 70, 75, 80, 85, 90]} sales_df = pd.DataFrame(data) # Устанавливаем 'Дата' в качестве индекса sales_df.set_index('Дата', inplace=True) # Вычисляем корреляцию между продажами телевизоров и ноутбуков correlation = sales_df['Продажи телевизоров'].corr(sales_df['Продажи ноутбуков']) print(f'Корреляция между продажами телевизоров и ноутбуков: {correlation:.2f}')
Результат:
Корреляция между продажами телевизоров и ноутбуков: 0.41
Вычисление корреляции может помочь в определении, существует ли статистически значимая связь между этими двумя временными рядами.
Заключение
Анализ временных рядов имеет множество практических применений, включая прогнозирование продаж, управление финансами, медицинские исследования и многое другое. Понимание временных рядов и умение проводить их анализ являются важными навыками для аналитиков данных и специалистов по машинному обучению. Мы надеемся, что эта статья помогла вам расширить ваши знания о работе с временными рядами и вдохновила вас на дальнейшие исследования в этой области.
ссылка на оригинал статьи https://habr.com/ru/articles/769756/
Добавить комментарий