Работа с временными рядами в Python. Часть 2

от автора

Добро пожаловать во вторую часть нашей серии статей «Работа с временными рядами в 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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *