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



    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    输出:

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5

    第二种为正常版本的:

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    输出为:

    20200713
    20:40:37
    
    • 1
    • 2

    当下时间的:

    import locale
    from datetime import datetime
    
    locale.setlocale(locale.LC_CTYPE, 'chinese')
    now = datetime.now()
    print(now.strftime("%Y年%#m月%d日"))
    
    》》》 2022年7月01日
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    数值转日期:

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

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    计算时间间隔:

    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天
    
    • 1
    • 2
    • 3
    • 4
    • 5

    三天后的日期:

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5

    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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    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')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

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

    # 划为秒
    date_start_end.seconds # 得到:29168
    date_start_end.total_seconds() # 得到:48413168.683355
    
    # 划为天
    date_start_end.days
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

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

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

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

    下面是假设检验:

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

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

    pip install pymannkendall
    
    • 1

    来看一个案例:

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    下面是结果解释:

    • 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)
    
    • 1
    • 2
    • 3

    在这里插入图片描述

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

  • 相关阅读:
    ES6 Promise、Generator与async简单介绍与应用
    再来谈谈如何从binlog文件恢复误update的数据,模拟Oracle的闪回功能
    x86_64、AArch64、ARM32、LoongArch64、RISC-V
    yakit使用爆破编码明文_dnslog使用
    220V转18V非隔离降压芯片:满足多种应用需求
    linux安装nginx1.9.9
    SpringBoot使用Swagger2创建API文档
    JavaScript 基础知识|基础运算符
    【考研英语语法】状语从句精讲
    我的网站被攻击了,运维大佬给了我自动封禁ip的脚本。
  • 原文地址:https://blog.csdn.net/sinat_26917383/article/details/125553767