Время как последовательность — это метод прогнозирования будущего на основе анализа данных из прошлого. В отличие от регрессии, временной ряд обязательно должен иметь время в качестве индекса.
Благодаря тому, что время является индексом, существует множество специализированных методов обработки данных, основанных на времени.
Анализ временных рядов в исследованиях аспирантов
В этом примере мы используем данные с сайта yz.chsi.com.cn для тестирования анализа временных рядов. Сайт предоставляет доступ к различным данным, которые можно использовать для анализа.
Данные:
Автор отмечает, что многие данные имеют сильную корреляцию, и информация о прошлом может помочь предсказать будущее. Хотя некоторые считают, что внешние факторы могут влиять на точность прогнозов, автор предлагает сосредоточиться на внутренних факторах, которые могут определять данные.
Подготовка
Сначала необходимо подготовить инструменты и выбрать язык программирования. Автор использует Python 3.8 и библиотеку statsmodels. Также упоминаются другие библиотеки, такие как pandas, numpy и matplotlib.
Для анализа используется код на Python:
import pandas as pd # 加载pandas库
df = pd.read_excel('./postgrad.xlsx', index_col='年份') # 读取数据,并把‘年份’作为index
Параметр df будет содержать следующие данные:
Год | Количество заявок (млн) | Количество принятых (млн) |
---|---|---|
1994 | 11,4 | 4,2 |
1995 | 15,5 | 4 |
... | ... | ... |
2020 | 341 | 111,4 |
Затем автор использует код для построения графика:
import matplotlib.pyplot as plt # 加载matplotlib库
plt.rcParams['font.family'] = ['SimHei'] # 用来解决画图不显示中文的问题
plt.rcParams['axes.unicode_minus'] = False #
df.plot()
График автоматически генерируется после вызова функции plot().
Далее рассматривается автокорреляционная функция (ACF), которая является важной частью анализа временных рядов. ACF измеряет сходство между значениями временного ряда в разные моменты времени.
Пример кода на Python для вычисления ACF:
from statsmodels.tsa import stattools # 加载统计工具
stattools.acf(df['报名人数(万人)']) # 使用acf函数查看自相关,这块必须把数据单独处理
Этот код позволяет получить данные автокорреляции. Затем автор строит график ACF для визуализации результатов.
Из графика видно, что после третьего порядка автокорреляция начинает уменьшаться, что указывает на нестационарность ряда и наличие тренда и колебаний. Последовательность без тренда: ACF затухает быстро
Чисто случайная последовательность
Рисунок 1.
Короткая автокорреляция
Рисунок 2.
Последовательность с чередованием: ACF чередуется
Нестационарная последовательность: ACF затухает медленно, временной ряд имеет явный тренд
Определённый тренд
Рисунок 4.
Случайный тренд
Рисунок 5.
В ACF есть периодичность: временной ряд периодический и сезонный
Рисунки 6 и 7.
Автокорреляция — это статистическая взаимосвязь между функцией (сигналом) и её сдвинутой копией.
Частичная автокорреляция показывает связь между ошибкой предсказания текущего значения временного ряда и ошибкой предсказания предыдущего значения этого же ряда.
Обрезка — это свойство временного ряда, при котором автокорреляции после некоторого лага равны нулю.
Если PACF после какого-то лага становится незначимой, то говорят об «обрыве» или «структуре» на этом лаге.
Если ACF после какого-то лага становится незначима, то говорят о «случайном блуждании со сносом» (или просто «случайном блуждании»).
Срез — это ситуация, когда автокорреляции становятся незначимыми на всех лагах.
Если PACF становится незначимой после одного лага, то процесс является белым шумом.
Процесс является «обратным случайным блужданием», если ACF становится незначимой после первого лага.
Коинтеграция — свойство нескольких нестационарных временных рядов, заключающееся в существовании некоторой их стационарной линейной комбинации.
В данном тексте приведены примеры расчётов для двух временных рядов: «количество зарегистрированных участников» и «количество зачисленных участников». Для каждого из них рассчитаны ACF и PACF, а также проведён анализ на стационарность.
Для обоих рядов выявлена нестационарность, что говорит о необходимости применения методов, которые позволят сделать ряды стационарными. Одним из таких методов является взятие разности рядов.
Также в тексте упоминается метод проверки на стационарность — ADF-тест (Augmented Dickey–Fuller test). Приведены результаты теста для обоих рядов, которые подтверждают нестационарность данных.
Кроме того, в тексте говорится о том, что для получения стационарных рядов можно использовать метод взятия разности первого порядка. Это означает, что из значений ряда вычитаются предыдущие значения. ``` signdiff = pd.DataFrame() signdiff['一阶差分'] = df['报名人数(万人)'].diff().dropna() signdiff.plot() dickey(signdiff['一阶差分'])
| Условие | Значение |
| --- | --- |
| Test Statistic Value | -1,731451 |
| p-value | 0,414985 |
| Lags Used | 1 |
| Number of Observations Used | 24 |
| Critical Value (1%) | -3,737709 |
| Critical Value (5%) | -2,992216 |
| Critical Value (10%) | -2,635747 |
Всё ещё недостаточно стабильно.
enrolldiff = pd.DataFrame() enrolldiff['一阶差分'] = df['录取人数(万人)'].diff().dropna() enrolldiff.plot() dickey(enrolldiff)
| Условие | Значение |
| --- | --- |
| Test Statistic Value | -3,094678 |
| p-value | 0,02695 |
| Lags Used | 9 |
| Number of Observations Used | 15 |
| Critical Value (1%) | -3,964443 |
| Critical Value (5%) | -3,084908 |
| Critical Value (10%) | -2,681814 |
После однократного разностного анализа p-значение для числа зачисленных студентов меньше 0,05, что достигает уровня значимости.
#### Разностный анализ более высокого порядка
Мы можем продолжить разностный анализ более высокого порядка.
#### Второй порядок
```py
signdiff['二阶差分'] = df['报名人数(万人)'].diff(periods=2)
signdiff = signdiff.dropna()
signdiff.plot()
dickey(signdiff['二阶差分'])
Условие | Значение |
---|---|
Test Statistic Value | -0,33767 |
p-value | 0,919997 |
Lags Used | 4 |
Number of Observations | Used 20 |
Critical Value (1%) | -3,809209 |
Critical Value (5%) | -3,021645 |
Critical Value (10%) | -2,650713 |
Второй порядок разностного анализа всё ещё недостаточен для значимости.
signdiff['三阶差分'] = df['报名人数(万人)'].diff(periods=3)
signdiff = signdiff.dropna()
signdiff.plot()
dickey(signdiff['三阶差分'])
Условие | Значение |
---|---|
Test Statistic Value | -3,642791 |
p-value | 0,004994 |
Lags Used | 1 |
Number of Observations | Used 22 |
Critical Value (1%) | -3,769733 |
Critical Value (5%) | -3,005426 |
Critical Value (10%) | -2,642501 |
Трёхкратный разностный анализ наконец-то стал стабильным.
Однако слишком много различий, возможно, данные не имеют смысла, и хотя точность прогноза может быть низкой, всё же стоит использовать исходные данные.
Рисунок: diff
В этом случае мы сравниваем p=0, 1, 2, 3, 4 и q=0, 1, 2. В этот момент создание тепловой карты будет очень эффективным.
Функция тепловой карты
import numpy as np
from statsmodels.tsa import arima_model
import itertools
import seaborn as sns #热力图
import warnings
warnings.filterwarnings("ignore")
def thermodynamicOrder(df, ar=4, ma=2):
results_aic = pd.DataFrame(\
index=['AR{}'.format(i) for i in range(0, ar+1)],\
columns=['MA{}'.format(i) for i in range(0, ma+1)])
for p, q in itertools.product(range(0, ar+1), range(0, ma+1)):
if p==0 and q==0:
results_aic.loc['AR{}'.format(p), 'MA{}'.format(q)] = np.nan
continue
try:
results = arima_model.ARMA(df, (p, q)).fit()
#返回不同pq下的model的BIC值
results_aic.loc['AR{}'.format(p), 'MA{}'.format(q)] = results.aic
except:
continue
results_aic = results_aic[results_aic.columns].astype(float)
fig, ax = plt.subplots(figsize=(10, 8))
ax = sns.heatmap(results_aic,
#mask=results_aic.isnull(),
ax=ax,
annot=True, #将数字显示在热力图上
fmt='.2f',
)
ax.set_title('AIC')
plt.show()
Используя исходные данные, просмотрите тепловую карту.
thermodynamicOrder(df['报名人数(万人)'], 4, 2)
Можно получить p=3, q=0 эффект лучше всего.
Использование однократной разницы для просмотра тепловой карты.
thermodynamicOrder(enrolldiff['一阶差分'], 4, 2)
Можно получить p=2, q=0 эффект лучше всего.
Поскольку периодичность не является сильной, мы используем модель ARMA.
Однократная разница должна быть восстановлена.
def revert(diffValues, *lastValue):
for i in range(len(lastValue)):
result = []
lv = lastValue[i]
for dv in diffValues:
lv = dv + lv
result.append(lv)
diffValues = result
return diffValues
Прогнозирование будущих данных
fig, ax = plt.subplots(figsize=(15, 6))
df.plot(ax=ax)
signarma = arima_model.ARMA(df['报名人数(万人)'], (3, 0)).fit()
signfuture = pd.DataFrame({'报名模型': signarma.fittedvalues}, index=signarma.fittedvalues.index)
signfuture = signfuture.append(pd.DataFrame({'报名模型': signarma.forecast(4)[0]}, index=['2021年','2022年','2023年','2024年']))
signfuture.plot(ax=ax)
enrollarma = arima_model.ARMA(enrolldiff['一阶差分'], (2, 0)).fit()
enrollfuture = pd.DataFrame({'录取模型': revert(enrollarma.fittedvalues, df['录取人数(万人)'][0])}, index=enrollarma.fittedvalues.index)
enrollfuture = enrollfuture.append(pd.DataFrame({'录取模型':revert(enrollarma.forecast(5)[0], df['录取人数(万人)'][-2])}, index=['2020年','2021年','2022 год','2023 год','2024 год']))
enrollfuture.plot(ax=ax)
``` Посмотрим, как выглядят данные о будущем~
| Время | Прогноз регистрации |
| --- | --- |
| 2021 год | 386.760535 |
| 2022 год | 425.996818 |
| 2023 год | 458.785991 |
| 2024 год | 485.769711 |
| Время | Прогноз приёма |
| --- | --- |
| 2020 год | 69.985935 |
| 2021 год | 76.769525 |
| 2022 год | 81.898363 |
| 2023 год | 83.108294 |
| 2024 год | 84.263803 |
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )