笔记 | 不规则波动的时间序列数据处理与关联模型小结


1 时序模型的学习笔记

关于时序数据的关联模型,笔者陆陆续续更新了一些,包括了,
传统的时序模型学习
statsmodels︱python常规统计模型库
python实现logistic增长模型

还有两款ML上面的prophet + kats:
R+python︱Facebook大规模时序预测『真』神器——Prophet(遍地代码图)
Kats时间序列开源库的使用笔记

还有总结帖:
回顾︱时间序列预测与分解有哪些模型?(一)

其中statsmodels 包含:
在这里插入图片描述

那么能够处理那种比较不规则波动时序的,
常见有:ARMA,autoregressions等
在多项式回归里面,有polyfit 、curve_fit等

2 时间序列数据基本处理

参考:
python中各种时间格式的转换
python中时间日期格式的类型的转换(含pandas)

2.1 时间字符串、时间戳之间的转换

import time
str_time = "20200713203740"
time_temp = time.strptime(str_time, "%Y%m%d%H%M%S") # 字符串格式化成时间格式
time_stamp = time.mktime(time_temp)         # 格式化后的时间转换成时间戳
 
print(time_temp)
print(time_stamp)

输出:

print(time_temp)
time.struct_time(tm_year=2020, tm_mon=7, tm_mday=13, tm_hour=20, tm_min=37, tm_sec=40, tm_wday=0, tm_yday=195, tm_isdst=-1)

print(time_stamp)
1594643860.0

第二种为正常版本的:

from datetime import datetime
x = 1594643860
y_m_d = datetime.fromtimestamp(x).strftime('%Y%m%d')
h_s_m = datetime.fromtimestamp(x).strftime('%H:%S:%M')
print(y_m_d)
print(h_s_m)

输出为:

20200713
20:40:37

当下时间的:

import locale
from datetime import datetime

locale.setlocale(locale.LC_CTYPE, 'chinese')
now = datetime.now()
print(now.strftime("%Y年%#m月%d日"))

》》》 2022年7月01日

数值转日期:

dt = 20180908
datetime.strptime(str(dt),'%Y%m%d')
#datetime.datetime(2018, 9, 8, 0, 0)

2.2 时间格式化

import datetime
# 将时间字符串转换成格式化的时间格式
time = "20190617 00:00:00"
time = datetime.datetime.strptime(time, "%Y%m%d %H:%M:%S")
print(time)
>>>  2019-06-17 00:00:00


# 将格式化的时间格式,转换成时间字符串
timestr = datetime.datetime.strftime(time, "%Y%m%d %H:%M:%S")
print(timestr)
>>> 20190617 00:00:00

2.3 时间格式的加减

在原来的时间上加6天:

import datetime
# 将时间字符串转换成格式化的时间格式
time = "20190617 00:00:00"
time = datetime.datetime.strptime(time, "%Y%m%d %H:%M:%S")
 
# 在原来的时间上加6天
time = time + datetime.timedelta(days=6)
print(time)

计算时间间隔:

import datetime
d1 = datetime.datetime.strptime('2019-05-31 15:12:54', '%Y-%m-%d %H:%M:%S')
d2 = datetime.datetime.strptime('2019-05-22 15:12:54', '%Y-%m-%d %H:%M:%S')
delta = d1 - d2
print(delta.days) # 9 间隔9天

三天后的日期:

import datetime
now = datetime.datetime.now()
delta = datetime.timedelta(days=3)
n_days = now + delta
print(n_days.strftime('%Y-%m-%d %H:%M:%S')) # 2019-06-03 15:38:32

3天前的日期:

import datetime
now = datetime.datetime.now()
delta = datetime.timedelta(days=3)
n_days = now - delta
print(n_days.strftime('%Y-%m-%d %H:%M:%S')) # 2019-05-28 15:39:33

2.4 时间差转化为秒


import pandas as pd
import datetime
date_end = pd.to_datetime(datetime.datetime.now()) # Timestamp('2021-05-19 08:06:08.683355')
date_start = pd.to_datetime('2019/11/06') # Timestamp('2019-11-06 00:00:00')
date_start_end = date_end - date_start # 时间间隔,Timedelta('560 days 08:06:08.683355')

>>> Timedelta('968 days 11:20:02.506161')

时间差如上,需要拿到按天,月,日,时的间隔:

# 划为秒
date_start_end.seconds # 得到:29168
date_start_end.total_seconds() # 得到:48413168.683355

# 划为天
date_start_end.days

2.5 pandas提取时间

import pandas as pd #导入模块
df=pd.read_excel(r'C:\Users\CHENRUI\Desktop\测试\时间和if判断.xlsx') #文件路径
df['时间']=pd.to_datetime(df['时间']) #时间列转换成时间格式

# 提取月
df['月份']=df['时间'].dt.month  #用dt.month提取月份,同理dt.year就是提取年份
print(df)

#提取年
df6['Birth'].dt.year

#提取日
df6['Birth'].dt.day

2.6 [函数] 时间自动往后加

import pandas as pd
from datetime import datetime,timedelta
def generation_time_series(input_date = '20220609',gap_day = 36):
    '''
    参数:
        input_date = '20220609'
        gap_day = 36
    '''
    end_date = datetime.strptime(input_date, "%Y%m%d") + timedelta(days=gap_day)
    end_date = end_date.strftime('%Y%m%d')
    dates = pd.date_range(start=input_date, end=end_date)
    return dates

generation_time_series(input_date = '20220609',gap_day = 36)
>>> 
DatetimeIndex(['2022-06-09', '2022-06-10', '2022-06-11', '2022-06-12',
               '2022-06-13', '2022-06-14', '2022-06-15', '2022-06-16',
               '2022-06-17', '2022-06-18', '2022-06-19', '2022-06-20',
               '2022-06-21', '2022-06-22', '2022-06-23', '2022-06-24',
               '2022-06-25', '2022-06-26', '2022-06-27', '2022-06-28',
               '2022-06-29', '2022-06-30', '2022-07-01', '2022-07-02',
               '2022-07-03', '2022-07-04', '2022-07-05', '2022-07-06',
               '2022-07-07', '2022-07-08', '2022-07-09', '2022-07-10',
               '2022-07-11', '2022-07-12', '2022-07-13', '2022-07-14',
               '2022-07-15'],
              dtype='datetime64[ns]', freq='D')

3 时间趋势预测:Mann-Kendall检验

来源:使用Mann-Kendall检验分析时间序列数据的趋势

Mann-Kendall检验可以用来判断时间序列数据是否存在趋势。这是非参数检验,无需假设数据具有正态性。

下面是假设检验:

  • H0(零假设):数据不存在趋势。
  • H1(备择假设):数据具有趋势。(可能是向上或者向下)

如果p值低于某个显著性水平(常见的有0.1, 0.05和0.01), 就说明时间序列数据具有趋势。

pip install pymannkendall

来看一个案例:

data = [31, 29, 28, 28, 27, 26, 26, 27, 27, 27, 28, 29, 30, 29, 30, 29, 28]

#perform Mann-Kendall Trend Test
import pymannkendall as mk

mk.original_test(data)
>>> Mann_Kendall_Test(trend='no trend', h=False, p=0.422586268671707,
                  z=0.80194241623, Tau=0.147058823529, s=20.0,
                  var_s=561.33333333, slope=0.0384615384615, intercept=27.692307692)

下面是结果解释:

  • trend: 数据的趋势,可能的结果有increasing, decreasing, or no trend
  • h: 如果有趋势就是True,反之为False
  • p: 检验的p值
  • z: The normalize test statistic.
  • Tau: Kendall Tau.
  • s: Mann-Kendal’s score
  • var_s: Variance S
  • slope: Theil-Sen estimator/slope
  • intercept: Intercept of Kendall-Theil Robust Line

我们主要关心p值,p值说明了数据中是否存在显著的趋势。

在这个例子中,p值是0.4226, 比0.05还要高,因此这组时间序列数据中没有显著趋势。

在做Mann-Kendall趋势检验时,我们可以使用matplotlib快速地画出实际数据。

import matplotlib.pyplot as plt

plt.plot(data)

在这里插入图片描述

笔者使用心得:
这个还需搭配时间段筛选,上图中就是,5-12期需要与其他几期进行拆分,才能看出趋势项
短时序的预测不是特别准确,特别是只有几个点的时候,基本失效
这一算法在Kats有被使用进,趋势检测当中,但是整体来看Kats效果不太好

猜你喜欢

转载自blog.csdn.net/sinat_26917383/article/details/125553767