Аналитика данных стала неотъемлемой частью современного бизнеса и научных исследований. И одним из ключевых аспектов анализа данных являются временные ряды. Эффективная работа с временными рядами играет критическую роль в прогнозировании, стратегическом планировании и принятии решений в различных отраслях.
Временные ряды — это наборы данных, где каждая точка данных связана с определенным моментом времени. Это может быть что угодно, от ежедневных финансовых показателей до ежечасных кликов на веб-сайте или даже месячных показателей погоды. Зачем нам это нужно? Потому что временные ряды предоставляют нам ценную информацию о том, как меняются данные со временем.
Области, где временные ряды играют решающую роль:
1. Финансовая аналитика: Прогнозирование цен акций, анализ рыночных тенденций и определение оптимального времени для инвестиций.
2. Маркетинг и анализ пользовательской активности: Отслеживание изменений в поведении пользователей на веб-сайте, прогнозирование спроса на товары и услуги.
3. Прогнозирование спроса: Определение оптимального уровня запасов, чтобы избежать дефицита или избытка товаров.
4. Анализ временных данных о заболеваниях: Оценка распространения эпидемий, прогнозирование заболеваемости и смертности.
5. Климатические исследования: Изучение изменений в климатических параметрах, таких как температура и осадки, для анализа климатических тенденций.
6. Прогнозирование трафика: Анализ и прогнозирование трафика на веб-сайтах и в сетях.
7. Промышленное оборудование и обслуживание: Предсказание времени отказа оборудования и оптимизация производственных процессов.
Временные ряды также присутствуют в повседневной жизни: температурные измерения, динамика финансовых индексов или даже ежедневные показатели физической активности с помощью носимых устройств — все это временные ряды.
Временные ряды могут быть стационарными (когда статистические характеристики, такие как среднее и дисперсия, остаются постоянными во времени) или нестационарными (когда эти характеристики изменяются с течением времени). Понимание природы временного ряда важно для выбора подходящих методов анализа.
Основные характеристики временных рядов
Тренд: Тренд представляет собой долгосрочное изменение в данных. Это может быть рост или спад. Например, если продажи вашей компании растут каждый месяц в течение года, это будет проявление тренда.
Сезонность: Сезонность — это циклические изменения данных, которые повторяются с постоянным интервалом времени. Например, продажи игрушек могут расти перед праздниками и падать после них.
Шум: Шум представляет собой случайные колебания данных, которые не подчиняются определенным закономерностям. Это может быть вызвано различными факторами, такими как случайные события или ошибки измерения.
Циклы: Циклы — это долгосрочные колебания данных, которые не связаны с сезонностью. Например, экономические циклы могут вызывать волны роста и спада в продажах.
Стационарность: Стационарный временной ряд — это ряд, в котором статистические характеристики, такие как среднее и дисперсия, остаются постоянными с течением времени. Многие методы анализа временных рядов предполагают стационарность данных.
Автокорреляция: Автокорреляция — это корреляция между значениями ряда в разные моменты времени. Она может помочь выявить закономерности в данных.
Пропущенные значения: Временные ряды могут содержать пропущенные значения, которые требуется обработать перед анализом.
Подготовка к анализу
Прежде чем мы начнем работу, нам нужно убедиться, что у нас есть все необходимые библиотеки для анализа временных рядов:
1. pandas: Pandas — это библиотека для работы с данными, которая предоставляет удобные структуры данных, такие как DataFrame, и множество функций для анализа и манипуляции данными. Она идеально подходит для работы с временными рядами, так как позволяет легко хранить и анализировать временные данные.
2. numpy: NumPy — это библиотека для работы с массивами и матрицами чисел. Она полезна при выполнении вычислений над данными временных рядов.
3. matplotlib и seaborn: Эти библиотеки позволяют создавать графики и визуализации данных, что особенно важно при анализе временных рядов.
4. statsmodels: Statsmodels — это библиотека для статистического анализа данных. Она содержит множество методов для анализа временных рядов, включая модели ARIMA и SARIMA.
5. scikit-learn: Scikit-learn предоставляет множество инструментов для машинного обучения, включая модели регрессии и классификации, которые можно использовать для анализа временных рядов.
Устанавливаем:
!pip install pandas numpy matplotlib seaborn statsmodels scikit-learn
Теперь, когда у нас есть необходимые библиотеки, давайте перейдем к работе с датами и временем.
Одной из ключевых характеристик временных рядов является наличие временных меток, которые позволяют нам связывать данные с конкретными моментами времени. При работе с временными рядами необходимо уметь обращаться с датами и временем.
Для начала давайте создадим небольшой dataset с данными о продажах электроники за несколько месяцев. Для примера давайте представим, что у нас есть следующие данные:
import pandas as pd data = {'Дата': ['2023-01-01', '2023-02-01', '2023-03-01', '2023-04-01', '2023-05-01'], 'Продажи': [1000, 1200, 1300, 1100, 1400]} df = pd.DataFrame(data) # Преобразуем столбец 'Дата' в формат даты df['Дата'] = pd.to_datetime(df['Дата']) print(df)
Результат будет следующим:
Дата Продажи 0 2023-01-01 1000 1 2023-02-01 1200 2 2023-03-01 1300 3 2023-04-01 1100 4 2023-05-01 1400
Теперь у нас есть DataFrame с данными о продажах и столбцом ‘Дата’, который имеет тип datetime64. Это позволяет нам выполнять различные операции, такие как выбор данных по дате или вычисление временных интервалов.
Пример:
# Выбор данных по диапазону дат subset = df[(df['Дата'] >= '2023-03-01') & (df['Дата'] <= '2023-04-30')] print(subset)
Вывод:
Дата Продажи 2 2023-03-01 1300 3 2023-04-01 1100
Таким образом, работа с датами и временем в pandas позволяет нам легко фильтровать и анализировать данные временных рядов.
Обработка пропущенных значений
Пропущенные значения — это обычное явление при работе с данными временных рядов. Они могут возникать по разным причинам, например, из-за ошибок при сборе данных или временных перерывов в измерениях. Поэтому важно знать, как обрабатывать пропущенные значения.
Давайте рассмотрим, как можно обработать пропущенные значения в DataFrame с помощью pandas. Для примера допустим, что у нас есть следующий dataset:
import pandas as pd data = {'Дата': ['2023-01-01', '2023-02-01', '2023-03-01', '2023-04-01', '2023-05-01'], 'Продажи': [1000, None, 1300, 1100, 1400]} df = pd.DataFrame(data) # Преобразуем столбец 'Дата' в формат даты df['Дата'] = pd.to_datetime(df['Дата']) print(df)
Результат:
Дата Продажи 0 2023-01-01 1000.0 1 2023-02-01 NaN 2 2023-03-01 1300.0 3 2023-04-01 1100.0 4 2023-05-01 1400.0
Как видите, у нас есть пропущенное значение (NaN) в столбце ‘Продажи’. Существует несколько способов обработки таких значений:
1. Удаление строк с пропущенными значениями:
df.dropna(inplace=True)
Этот метод удаляет строки, содержащие пропущенные значения. Важно помнить, что это может привести к потере данных.
2. Замена пропущенных значений:
df.fillna(0, inplace=True)
Здесь мы заменяем все пропущенные значения на 0. Вы можете выбрать другое значение для замены вместо 0 в зависимости от контекста.
3. Интерполяция:
df.interpolate(inplace=True)
Интерполяция позволяет заполнить пропущенные значения на основе соседних значений. Это может быть полезно, если данные имеют некоторую структуру.
Обработка пропущенных значений зависит от конкретной задачи и данных временных рядов. Важно выбирать подходящий метод в каждом случае.
Анализ временных рядов
Мы переходим к разделу анализа временных рядов, который поможет нам раскрывать информацию и закономерности, скрытые в данных. Этот этап позволяет нам понять структуру временных рядов, определить их стационарность и выделить основные компоненты, такие как тренд, сезонность и шум.
Стационарность временных рядов
Стационарность — одно из важнейших свойств временных рядов. Стационарный ряд — это ряд, в котором статистические характеристики, такие как среднее и дисперсия, остаются постоянными во времени. Это свойство позволяет нам строить надежные модели и прогнозировать будущие значения.
1. Тесты на стационарность:
Первый шаг в анализе временных рядов — проверка стационарности. Для этого существует несколько статистических тестов. Один из них — тест Дики-Фуллера. Давайте применим его к нашему небольшому dataset с данными о продажах в условном филиале МВидео:
import pandas as pd import matplotlib.pyplot as plt from statsmodels.tsa.stattools import adfuller # Создаем dataset с данными о продажах data = {'Дата': ['2023-01-01', '2023-02-01', '2023-03-01', '2023-04-01', '2023-05-01'], 'Продажи': [1000, 1200, 1300, 1100, 1400]} df = pd.DataFrame(data) # Преобразуем столбец 'Дата' в формат даты df['Дата'] = pd.to_datetime(df['Дата']) # Построим график продаж plt.plot(df['Дата'], df['Продажи']) plt.title('Продажи в магазине МВидео') plt.xlabel('Дата') plt.ylabel('Продажи') plt.show() # Проведем тест Дики-Фуллера на стационарность result = adfuller(df['Продажи']) print('ADF Statistic: %f' % result[0]) print('p-value: %f' % result[1]) print('Critical Values:') for key, value in result[4].items(): print('\t%s: %.3f' % (key, value))

На выходе мы получим статистику теста Дики-Фуллера и p-значение. Если p-значение меньше уровня значимости (обычно 0.05), то мы можем отклонить нулевую гипотезу о нестационарности ряда и считать его стационарным.
2. Преобразование ряда для достижения стационарности:
Если начальный ряд не является стационарным, то его можно преобразовать. Например, можно вычесть тренд и сезонные компоненты, чтобы получить стационарный остаток.
# Преобразование для удаления тренда df['Продажи_без_тренда'] = df['Продажи'] - df['Продажи'].rolling(window=2).mean() # Преобразование для удаления сезонности (в данном случае просто разница между текущим и предыдущим значением) df['Продажи_стационарные'] = df['Продажи_без_тренда'].diff() # Удалим первые строки с пропущенными значениями df.dropna(inplace=True) # Построим графики plt.plot(df['Дата'], df['Продажи_без_тренда'], label='Без тренда') plt.plot(df['Дата'], df['Продажи_стационарные'], label='Стационарные') plt.legend() plt.title('Преобразованные продажи') plt.xlabel('Дата') plt.ylabel('Продажи') plt.show()

Теперь у нас есть стационарный ряд Продажи_стационарные, который мы можем анализировать и моделировать.
Компоненты временных рядов
Временные ряды обычно состоят из трех основных компонентов: тренда, сезонности и шума (остатка). Понимание этих компонентов помогает нам лучше понимать структуру ряда и выбирать подходящие методы анализа.
1. Тренд:
Тренд — это долгосрочное изменение в данных, которое может быть восходящим (рост), нисходящим (падение) или горизонтальным (без изменений). Он представляет собой общее направление движения данных.
Посмотрим на примере:
# Создаем dataset с данными о продажах с трендом data_trend = {'Дата': ['2023-01-01', '2023-02-01', '2023-03-01', '2023-04-01', '2023-05-01'], 'Продажи': [1000, 1200, 1400, 1600, 1800]} df_trend = pd.DataFrame(data_trend) # Преобразуем столбец 'Дата' в формат даты df_trend['Дата'] = pd.to_datetime(df_trend['Дата']) # Построим график продаж с трендом plt.plot(df_trend['Дата'], df_trend['Продажи']) plt.title('Продажи с трендом (рост)') plt.xlabel('Дата') plt.ylabel('Продажи') plt.show()

На графике видно, что продажи увеличиваются со временем. Это пример тренда восходящего направления.
2. Сезонность:
Сезонность — это периодические колебания в данных, которые повторяются через равные временные интервалы. Сезонность может быть годовой, месячной, недельной и т. д. Она связана с событиями, которые регулярно влияют на данные.
# Создаем dataset с данными о продажах с сезонностью data_seasonal = {'Дата': ['2023-01-01', '2023-02-01', '2023-03-01', '2023-04-01', '2023-05-01'], 'Продажи': [1000, 1200, 900, 1100, 1400]} df_seasonal = pd.DataFrame(data_seasonal) # Преобразуем столбец 'Дата' в формат даты df_seasonal['Дата'] = pd.to_datetime(df_seasonal['Дата']) # Построим график продаж с сезонностью plt.plot(df_seasonal['Дата'], df_seasonal['Продажи']) plt.title('Продажи с сезонностью') plt.xlabel('Дата') plt.ylabel('Продажи') plt.show()

На графике видно, что продажи имеют периодические колебания, которые повторяются примерно каждый месяц.
3. Шум:
Шум (остаток) — это случайные изменения в данных, которые не могут быть объяснены трендом или сезонностью. Он представляет собой нерегулярные колебания и вариации в данных.
# Создаем dataset с данными о продажах с шумом data_noise = {'Дата': ['2023-01-01', '2023-02-01', '2023-03-01', '2023-04-01', '2023-05-01'], 'Продажи': [1000, 1200, 1050, 1150, 1100]} df_noise = pd.DataFrame(data_noise) # Преобразуем столбец 'Дата' в формат даты df_noise['Дата'] = pd.to_datetime(df_noise['Дата']) # Построим график продаж с шумом plt.plot(df_noise['Дата'], df_noise['Продажи']) plt.title('Продажи с шумом') plt.xlabel('Дата') plt.ylabel('Продажи') plt.show()

На графике видно, что продажи имеют случайные колебания, которые не имеют явного тренда или сезонности. Это пример шума.
Автокорреляция и частичная автокорреляция
Автокорреляция — это мера корреляции между временным рядом и его лагированными (отстающими) значениями. Это позволяет нам определить зависимость текущих значений от предыдущих.
Частичная автокорреляция — это мера корреляции между временным рядом и его лагированными значениями с учетом корреляции в промежуточных лагах. Она помогает выявить «чистую» зависимость от определенных отстающих значений, исключая влияние промежуточных лагов.
Представим, что у нас есть временной ряд данных о температуре каждый час:
import pandas as pd import numpy as np import matplotlib.pyplot as plt from statsmodels.graphics.tsaplots import plot_acf, plot_pacf # Создаем небольшой временной ряд температуры np.random.seed(0) dates = pd.date_range(start='2023-01-01', end='2023-01-07', freq='H') temperature = np.random.normal(loc=25, scale=5, size=len(dates)) df_temperature = pd.DataFrame({'Дата': dates, 'Температура': temperature}) # Устанавливаем 'Дата' в качестве индекса df_temperature.set_index('Дата', inplace=True) # Построим график временного ряда plt.figure(figsize=(12, 4)) plt.plot(df_temperature.index, df_temperature['Температура']) plt.title('Временной ряд температуры') plt.xlabel('Дата и время') plt.ylabel('Температура (°C)') plt.grid(True) plt.show() # Рассчитываем автокорреляцию и частичную автокорреляцию plt.figure(figsize=(12, 6)) plt.subplot(211) plot_acf(df_temperature['Температура'], lags=50, ax=plt.gca()) plt.title('Автокорреляция') plt.subplot(212) plot_pacf(df_temperature['Температура'], lags=50, ax=plt.gca()) plt.title('Частичная автокорреляция') plt.tight_layout() plt.show()

На графиках автокорреляции и частичной автокорреляции вы можете увидеть значимые лаги, которые могут помочь в выборе параметров модели для анализа и прогнозирования временного ряда температуры. Эти графики помогают определить структуру и зависимости в данных.
Примеры на практике
В этом разделе мы рассмотрим несколько практических примеров использования анализа временных рядов для решения разнообразных задач.
Прогнозирование продаж на основе временных рядов продаж электроники
В этом примере мы будем использовать данные о ежемесячных продажах электроники в магазине МВидео для прогнозирования будущих продаж.
Cоздадим небольшой dataset с данными о продажах. В качестве исходных данных предположим следующие продажи за последние два года:
import pandas as pd import numpy as np # Создаем даты с января 2022 года по декабрь 2023 года dates = pd.date_range(start='2022-01-01', end='2023-12-31', freq='M') # Генерируем случайные продажи в интервале от 1000 до 5000 sales = np.random.randint(1000, 5000, size=len(dates)) # Создаем DataFrame sales_df = pd.DataFrame({'Дата': dates, 'Продажи': sales}) # Устанавливаем 'Дата' в качестве индекса sales_df.set_index('Дата', inplace=True) # Выводим первые несколько строк print(sales_df.head())
Результат:
Продажи Дата 2022-01-31 1355 2022-02-28 4665 2022-03-31 3154 2022-04-30 3490 2022-05-31 3569
Визуализация данных
Перед тем как перейти к прогнозированию, давайте визуализируем данные о продажах, чтобы понять их структуру и особенности.
import matplotlib.pyplot as plt # Построим график продаж plt.figure(figsize=(12, 6)) plt.plot(sales_df.index, sales_df['Продажи'], marker='o', linestyle='-') plt.title('Продажи в магазине МВидео') plt.xlabel('Дата') plt.ylabel('Продажи') plt.grid(True) plt.show()

На графике видно, что у нас есть временной ряд продаж с некоторыми трендами и колебаниями.
Подготовка данных
Прежде чем перейти к прогнозированию, нам нужно подготовить данные. Это включает в себя обработку пропущенных значений и проверку стационарности ряда.
# Обработка пропущенных значений (если они есть) sales_df.dropna(inplace=True) # Проверка стационарности ряда from statsmodels.tsa.stattools import adfuller result = adfuller(sales_df['Продажи']) print('ADF статистика:', result[0]) print('p-значение:', result[1]) print('Критические значения:') for key, value in result[4].items(): print(f' {key}: {value}')
Результат:
ADF статистика: -3.336001912478917 p-значение: 0.013343910713214318 Критические значения: 1%: -3.859073285322359 5%: -3.0420456927297668 10%: -2.6609064197530863
Если p-значение ниже некоторого порогового значения (обычно 0.05), то мы можем считать ряд стационарным.
Выбор и обучение модели
После подготовки данных мы можем выбрать и обучить модель для прогнозирования. Для этого примера мы будем использовать модель ARIMA.
from statsmodels.tsa.arima.model import ARIMA # Обучение модели ARIMA model = ARIMA(sales_df['Продажи'], order=(1, 1, 1)) model_fit = model.fit() # Вывод статистики модели print(model_fit.summary())
Результат:
SARIMAX Results ============================================================================== Dep. Variable: Продажи No. Observations: 24 Model: ARIMA(1, 1, 1) Log Likelihood -197.611 Date: Mon, 18 Sep 2023 AIC 401.222 Time: 12:03:31 BIC 404.628 Sample: 01-31-2022 HQIC 402.078 - 12-31-2023 Covariance Type: opg ============================================================================== coef std err z P>|z| [0.025 0.975] ------------------------------------------------------------------------------ ar.L1 0.1787 0.252 0.709 0.478 -0.315 0.673 ma.L1 -1.0000 0.349 -2.868 0.004 -1.683 -0.316 sigma2 1.469e+06 2.37e-07 6.19e+12 0.000 1.47e+06 1.47e+06 =================================================================================== Ljung-Box (L1) (Q): 0.05 Jarque-Bera (JB): 0.87 Prob(Q): 0.82 Prob(JB): 0.65 Heteroskedasticity (H): 0.70 Skew: 0.34 Prob(H) (two-sided): 0.63 Kurtosis: 2.33 ===================================================================================
Оценка качества прогноза
После обучения модели мы можем оценить ее качество на основе имеющихся данных.
from sklearn.metrics import mean_squared_error, mean_absolute_error # Прогноз на основе обученной модели forecast = model_fit.forecast(steps=12) # Рассчитываем MSE и MAE mse = mean_squared_error(sales_df['Продажи'][-12:], forecast) mae = mean_absolute_error(sales_df['Продажи'][-12:], forecast) print(f'MSE: {mse}') print(f'MAE: {mae}')
Результат:
MSE: 1178795.2830408707 MAE: 906.8571433244668
Прогноз на будущее
Теперь, когда модель обучена и ее качество оценено, мы можем использовать ее для прогнозирования будущих значений.
# Прогноз на будущее (следующие 12 месяцев) forecast_future = model_fit.forecast(steps=12) # Создаем новый DataFrame для будущих значений future_dates = pd.date_range(start='2024-01-01', periods=12, freq='M') forecast_df = pd.DataFrame({'Дата': future_dates, 'Прогноз продаж': forecast_future}) # Присоединяем прогноз к исходному DataFrame sales_df = sales_df.append(forecast_df, ignore_index=True) # Визуализация исходных данных и прогноза plt.figure(figsize=(12, 6)) plt.plot(sales_df.index[:-12], sales_df['Продажи'][:-12], label='Исходные данные') plt.plot(sales_df.index[-12:], sales_df['Прогноз продаж'][-12:], label='Прогноз') plt.title('Прогноз продаж в магазине МВидео') plt.xlabel('Дата') plt.ylabel('Продажи') plt.legend() plt.grid(True) plt.show()

На графике показаны исходные данные о продажах и прогноз продаж на следующие 12 месяцев. Этот пример демонстрирует, как использовать анализ временных рядов для прогнозирования будущих продаж в магазине электроники.
Заключение
В данной статье мы рассмотрели основные концепции и методы работы с временными рядами в Python. Мы изучили, как импортировать данные временных рядов, визуализировать их, а также провели анализ стационарности и сезонности.
В следующей части нашей серии статей, мы погрузимся в более продвинутые аспекты работы с временными рядами. Мы рассмотрим, как использовать модели прогнозирования временных рядов, чтобы, например, прогнозировать погоду с учетом исторических данных. Мы также углубимся в анализ временных рядов с переменными интервалами, что может быть полезно в различных прикладных областях. Кроме того, мы уделим внимание совместным временным рядам, где мы сможем исследовать взаимосвязи между разными временными рядами и принимать более информированные решения.
ссылка на оригинал статьи https://habr.com/ru/articles/769190/
Добавить комментарий