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

2022-09-01 16:37:54 浏览数 (1)

文章目录

  • 1 时序模型的学习笔记
  • 2 时间序列数据基本处理
    • 2.1 时间字符串、时间戳之间的转换
    • 2.2 时间格式化
    • 2.3 时间格式的加减
    • 2.4 时间差转化为秒
    • 2.5 pandas提取时间
  • 3 时间趋势预测:Mann-Kendall检验

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 时间字符串、时间戳之间的转换

代码语言:javascript复制
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)

输出:

代码语言:javascript复制
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

第二种为正常版本的:

代码语言:javascript复制
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)

输出为:

代码语言:javascript复制
20200713
20:40:37

当下时间的:

代码语言:javascript复制
import locale
from datetime import datetime

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

》》》 2022年7月01日

数值转日期:

代码语言:javascript复制
dt = 20180908
datetime.strptime(str(dt),'%Y%m%d')
#datetime.datetime(2018, 9, 8, 0, 0)

2.2 时间格式化

代码语言:javascript复制
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天:

代码语言:javascript复制
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)

计算时间间隔:

代码语言:javascript复制
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天

三天后的日期:

代码语言:javascript复制
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天前的日期:

代码语言:javascript复制
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 时间差转化为秒

代码语言:javascript复制
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')

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

代码语言:javascript复制
# 划为秒
date_start_end.seconds # 得到:29168
date_start_end.total_seconds() # 得到:48413168.683355

# 划为天
date_start_end.days

2.5 pandas提取时间

代码语言:javascript复制
import pandas as pd #导入模块
df=pd.read_excel(r'C:UsersCHENRUIDesktop测试时间和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

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

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

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

下面是假设检验:

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

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

代码语言:javascript复制
pip install pymannkendall

来看一个案例:

代码语言:javascript复制
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快速地画出实际数据。

代码语言:javascript复制
import matplotlib.pyplot as plt

plt.plot(data)

笔者使用心得:

这个还需搭配时间段筛选,上图中就是,5-12期需要与其他几期进行拆分,才能看出趋势项

短时序的预测不是特别准确,特别是只有几个点的时候,基本失效

这一算法在Kats有被使用进,趋势检测当中,但是整体来看Kats效果不太好

0 人点赞