• Pandas数据分析基础之时间序列


    一、时间序列是什么

    时间序列在多个时间点观察或测量到的任何事物,很多都是固定频率出现 的,比如每15秒、每5分钟、每月。
    padnas提供了一组标准的时间序列处理工具和数据算法,基本的时间序列类型是以时间戳为索引的Series。
    当创建一个带有DatetimeIndex的Series时,pandas就会知道对象是一个时间序列,用Numpy的datetime64数据以纳秒形式存储时间。

    dates=[
        datetime(2020,1,2),datetime(2020,1,5),datetime(2020,1,7),
        datetime(2020,1,8),datetime(2020,1,10),datetime(2020,1,12)
    ]
    ts=pd.Series(np.random.randn(6),index=dates)
    ts
    2020-01-02 -0.140776
    2020-01-05 0.185088
    2020-01-07 0.555777
    2020-01-08 0.693348
    2020-01-10 -0.213715
    2020-01-12 -0.259721
    dtype: float64
    
    ts.index
    DatetimeIndex(['2020-01-02', '2020-01-05', '2020-01-07', '2020-01-08',
                   '2020-01-10', '2020-01-12'],
                  dtype='datetime64[ns]', freq=None)
    
    ts.index.dtype
    dtype('<M8[ns]')
    

    二、时间序列的选取-时间字符串/at_time/between_time/asof

    1.传入一个可以被解释为日期的字符串

    ts['1/10/2020']
    -0.3216128833894315
    ts['2020-01-02']
    0.47508960825683716
    
    #也可以只传入年或月
    longer_ts['2021']
    2021-01-01 1.596179
    2021-01-02 -0.458160
    2021-01-03 1.380482
    ...
    2021-12-29 0.343524
    2021-12-30 0.040584
    2021-12-31 -1.616620
    Freq: D, Length: 365, dtype: float64
    
    #通过日期进行切片
    ts[datetime(2020,1,7):]
    2020-01-07 0.555777
    2020-01-08 0.693348
    2020-01-10 -0.213715
    2020-01-12 -0.259721
    dtype: float64
    
    ts['1/6/2020':'1/11/2020']
    2020-01-07 0.555777
    2020-01-08 0.693348
    2020-01-10 -0.213715
    dtype: float64
    

    2.通过at_time获取指定时间点

    # 生成一个交易日内的日期范围和时间序列,以分为纬度
    rng=pd.date_range('2020-06-01 09:30','2020-06-01 15:59',freq='T')
    #生成5天的时间点
    rng=rng.append([rng+pd.offsets.BDay(i) for i in range(1,4)])
    ts=pd.Series(np.arange(len(rng),dtype=float),index=rng)
    

    #抽取指定时间点:10点0分的数据
    ts.at_time(time(10,0))
    

    3.通过between_time获取两个时间点之间的数据

    ts.between_time(time(10,0),time(10,1))
    

    4.通过asof获取最接近当前时间的数据
    asof解释:最后一行不是NaN值的值。通俗的说:假如我有一组数据,某个点的时候这个值是NaN,那就求这个值之前最近一个不是NaN的值是多少

    selection=pd.date_range('2020-06-01 10:00',periods=4,freq='B')
    ts.asof(selection)
    

    三、时间序列的生成-datetime/date_range(start,end,perios,freq)

    1.直接使用date_time生成

    dates=[
        datetime(2020,1,2),datetime(2020,1,5),datetime(2020,1,7),
        datetime(2020,1,8),datetime(2020,1,10),datetime(2020,1,12)
    ]
    ts=pd.Series(np.random.randn(6),index=dates)
    

    date_range可以生成指定长度的DatetimeIndex

    • 指定开始和结束
    pd.date_range('4/1/2020','6/1/2020')
    DatetimeIndex(['2020-04-01', '2020-04-02', '2020-04-03', '2020-04-04',
                   '2020-04-05', '2020-04-06', '2020-04-07', '2020-04-08',
                   '2020-04-09', '2020-04-10', '2020-04-11', '2020-04-12',
                   '2020-04-13', '2020-04-14', '2020-04-15', '2020-04-16',
                   '2020-04-17', '2020-04-18', '2020-04-19', '2020-04-20',
                   '2020-04-21', '2020-04-22', '2020-04-23', '2020-04-24',
                   '2020-04-25', '2020-04-26', '2020-04-27', '2020-04-28',
                   '2020-04-29', '2020-04-30', '2020-05-01', '2020-05-02',
                   '2020-05-03', '2020-05-04', '2020-05-05', '2020-05-06',
                   '2020-05-07', '2020-05-08', '2020-05-09', '2020-05-10',
                   '2020-05-11', '2020-05-12', '2020-05-13', '2020-05-14',
                   '2020-05-15', '2020-05-16', '2020-05-17', '2020-05-18',
                   '2020-05-19', '2020-05-20', '2020-05-21', '2020-05-22',
                   '2020-05-23', '2020-05-24', '2020-05-25', '2020-05-26',
                   '2020-05-27', '2020-05-28', '2020-05-29', '2020-05-30',
                   '2020-05-31', '2020-06-01'],
                  dtype='datetime64[ns]', freq='D')
    
    • 指定步长
    pd.date_range(start='4/1/2020',periods=20)
    DatetimeIndex(['2020-04-01', '2020-04-02', '2020-04-03', '2020-04-04',
                   '2020-04-05', '2020-04-06', '2020-04-07', '2020-04-08',
                   '2020-04-09', '2020-04-10', '2020-04-11', '2020-04-12',
                   '2020-04-13', '2020-04-14', '2020-04-15', '2020-04-16',
                   '2020-04-17', '2020-04-18', '2020-04-19', '2020-04-20'],
                  dtype='datetime64[ns]', freq='D')
    
    • 指定偏移量

    M:日历月末最后一天

    pd.date_range('1/1/2020','12/1/2020',freq='M')
    DatetimeIndex(['2020-01-31', '2020-02-29', '2020-03-31', '2020-04-30',
                   '2020-05-31', '2020-06-30', '2020-07-31', '2020-08-31',
                   '2020-09-30', '2020-10-31', '2020-11-30'],
                  dtype='datetime64[ns]', freq='M')
    
    

    BM:每月的最后个工作日,business end of month

    pd.date_range('1/1/2020','12/1/2020',freq='BM')
    DatetimeIndex(['2020-01-31', '2020-02-28', '2020-03-31', '2020-04-30',
                   '2020-05-29', '2020-06-30', '2020-07-31', '2020-08-31',
                   '2020-09-30', '2020-10-30', '2020-11-30'],
                  dtype='datetime64[ns]', freq='BM')
    

    自定义时间偏移,如h、4h、1h30min

    pd.date_range('1/1/2020',periods=10,freq='1h30min')
    DatetimeIndex(['2020-01-01 00:00:00', '2020-01-01 01:30:00',
                   '2020-01-01 03:00:00', '2020-01-01 04:30:00',
                   '2020-01-01 06:00:00', '2020-01-01 07:30:00',
                   '2020-01-01 09:00:00', '2020-01-01 10:30:00',
                   '2020-01-01 12:00:00', '2020-01-01 13:30:00'],
                  dtype='datetime64[ns]', freq='90T')
    

    四、时间序列的偏移量对照表-freq

    名称 偏移量类型 说明
    D Day 每日
    B BusinessDay 每工作日
    H Hour 每小时
    T或min Minute 每分
    S Second 每秒
    L或ms Milli 每毫秒
    U Micro 每微秒
    M MounthEnd 每月最后一个日历日
    BM BusinessMonthEnd 每月最后一个工作日
    MS MonthBegin 每月每一个工作日
    BMS BusinessMonthBegin 每月第一个工作日
    W-MON、W-TUE... Week 指定星期几(MON、TUE、WED、THU、FRI、SAT、SUM)
    WOM-1MON、WMON-2MON WeekOfMonth 产生每月第一、第二、第三或第四周的星期几
    Q-JAN、Q-FEB... QuaterEnd 对于以指定月份(JAN、FEB、MAR、APR、MAY、JUN、JUL、AUG、SEP、OCT、NOV、DEC)结束的年度,每季度最后一月的最后一个日历日
    BQ-JAN、BQ-FEB... BusinessQuaterEnd 对于以指定月份结束的年度,每季度最后一月的最后一个工作日
    QS-JAN、QS-FEB... QuaterBegin 对于以指定月份结束的年度,每季度最后一月的第一个日历日
    QS-JAN、QS-FEB... BusinessQuaterBegin 对于指定月份结束的年度,每季度最后一月的第一个工作日
    A-JAN、A-FEB... YearEnd 每年指定月份的最后一个日历日
    BA-JAN、BA-FEB BusinessYearEnd 每年指定月份的最后一个日历日
    AS-JAN、AS-FEB YearBegin 每年指定月份的第一个日历日
    BAS-JAN、BAS-FEB BusinessYearBegin 每年指定月份的第一个工作日

    例如,每月第3个星期五

    pd.date_range('1/1/2020','9/1/2020',freq='WOM-3FRI')
    DatetimeIndex(['2020-01-17', '2020-02-21', '2020-03-20', '2020-04-17',
                   '2020-05-15', '2020-06-19', '2020-07-17', '2020-08-21'],
                  dtype='datetime64[ns]', freq='WOM-3FRI')
    

    五、时间序列的前移或后移-shift/通过Day或MonthEnd

    shift方法用于执行单纯的前移或后移操作

    ts=pd.Series(np.random.randn(4),
                index=pd.date_range('1/1/2020',periods=4,freq='M'))
    ts
    2020-01-31 0.185458
    2020-02-29 0.549704
    2020-03-31 0.146584
    2020-04-30 0.983613
    Freq: M, dtype: float64
    

    向后移动一个月

    ts.shift(1,freq='M')
    2020-02-29 0.185458
    2020-03-31 0.549704
    2020-04-30 0.146584
    2020-05-31 0.983613
    Freq: M, dtype: float64
    

    向前移动3天

    ts.shift(-3,freq='D')
    2020-01-28 0.185458
    2020-02-26 0.549704
    2020-03-28 0.146584
    2020-04-27 0.983613
    dtype: float64
    

    通过Day或MonthEnd移动

    from pandas.tseries.offsets import Day,MonthEnd
    now=datetime(2020,1,27)
    now+3*Day()
    Timestamp('2020-01-30 00:00:00')
    now+MonthEnd()
    Timestamp('2020-01-31 00:00:00')
    

    五、时区处理-tz/tz_convert

    python的时区信息来自第三方库pytz,pandas包装了pytz的功能
    查看所有时区

    pytz.common_timezones
    

    转换时区- tz_convert

    rng=pd.date_range('3/9/2020 9:30',periods=6,freq='D',tz='UTC')
    ts=pd.Series(np.random.randn(len(rng)),index=rng)
    ts
    2020-03-09 09:30:00+00:00 -1.779006
    2020-03-10 09:30:00+00:00 -0.293860
    2020-03-11 09:30:00+00:00 -0.174114
    2020-03-12 09:30:00+00:00 0.749316
    2020-03-13 09:30:00+00:00 0.342134
    2020-03-14 09:30:00+00:00 1.101283
    Freq: D, dtype: float64
    
    ts.tz_convert('Asia/Shanghai')
    2020-03-09 17:30:00+08:00 -1.779006
    2020-03-10 17:30:00+08:00 -0.293860
    2020-03-11 17:30:00+08:00 -0.174114
    2020-03-12 17:30:00+08:00 0.749316
    2020-03-13 17:30:00+08:00 0.342134
    2020-03-14 17:30:00+08:00 1.101283
    Freq: D, dtype: float64
    

    六、时期及算术运算-period

    时期(period)表示的是时间区间,比如数日、数月、数季、数年等
    下面这个Period对象表示从2020年1月1日到2020年12月31日之间的整段时间

    p=pd.Period(2020,freq='A-DEC')
    p
    Period('2020', 'A-DEC')
    

    创建规则的时期范围

    #季度为Q生成13个时间
    pd.period_range("2019-01", periods=13, freq="Q")
    
    #Q代表季度为频率,默认的后缀为DEC代表一年以第1个月为结束【最后一个月为1月份】
    pd.period_range("2019-01", periods=13, freq="Q-JAN")
    
    # 以季度Q【年为频率】生成13个时间
    pd.period_range("2019-01", periods=13, freq="Y")
    
    #以季度Q【2个月为频率】生成13个时间
    pd.period_range("2019-01", periods=13, freq="2m")
    
    

    PeriodIndex类保存了一组Period,可以在pandas数据结构中用作轴索引

    rng=pd.period_range('1/1/2020','6/30/2020',freq='M')
    rng
    PeriodIndex(['2020-01', '2020-02', '2020-03', '2020-04', '2020-05', '2020-06'], dtype='period[M]', freq='M')
    
    pd.Series(np.random.randn(6),rng)
    2020-01 -1.050150
    2020-02 -0.828435
    2020-03 1.648335
    2020-04 1.476485
    2020-05 0.779732
    2020-06 -1.394688
    Freq: M, dtype: float64
    

    使用字符串创建PeriodIndex
    Q代表季度为频率,默认的后缀为DEC代表一年以第12个月为结束

    pd.PeriodIndex(['2020Q3','2020Q2','2020Q1'],freq='Q-DEC')
    

    Period和PeriodIndex互转-asfreq

    p=pd.Period('2020',freq='A-DEC')
    p.asfreq('M',how='start')
    Period('2020-01', 'M')
    
    p=pd.Period('2020-08',freq='M')
    p.asfreq('A-JUN')
    Period('2021', 'A-JUN')
    

    to_period可以将datetime转period

    rng=pd.date_range('1/1/2020',periods=6,freq='D')
    ts=pd.Series(np.random.randn(6),index=rng)
    
    ts
    2020-01-01 -1.536552
    2020-01-02 -0.550879
    2020-01-03 0.601546
    2020-01-04 -0.103521
    2020-01-05 0.445024
    2020-01-06 1.127598
    Freq: D, dtype: float64
    
    ts.to_period('M')
    2020-01 -1.536552
    2020-01 -0.550879
    2020-01 0.601546
    2020-01 -0.103521
    2020-01 0.445024
    2020-01 1.127598
    Freq: M, dtype: float64
    

    to_timespame可以将Period转换为时间戳

    ts.to_period('M').to_timestamp()
    

    七、频率转换-resample

    重采样(resampling)指将时间序列从一个频率转换到另一个频率的处理过程
    pandas对象都带有一个resample方法,是各种频率转换的函数

    降采样率

    #查看100天的采样
    rng=pd.date_range('1/1/2020',periods=100,freq='D')
    ts=pd.Series(np.random.randn(len(rng)),index=rng)
    
    # 转为一月的
    ts.resample('M').mean()
    2020-01-31 -0.049213
    2020-02-29 -0.155195
    2020-03-31 -0.000091
    2020-04-30 -0.023561
    Freq: M, dtype: float64
    
    

    分钟的采样转为5分钟的

    rng=pd.date_range('1/1/2020',periods=12,freq='T')
    ts=pd.Series(np.random.randn(len(rng)),index=rng)
    ts.resample('5min').sum()
    
    2020-01-01 00:00:00 1.376219
    2020-01-01 00:05:00 0.883248
    2020-01-01 00:10:00 -0.939534
    Freq: 5T, dtype: float64
    
    

    通过groupby进行采样,传入一个能够访问时间序列的索引上字段的函数

    rng=pd.date_range('1/1/2020',periods=100,freq='D')
    ts=pd.Series(np.random.randn(len(rng)),index=rng)
    
    ts.groupby(lambda x:x.month).mean()
    2020-01-31 0.182420
    2020-02-29 0.200134
    2020-03-31 -0.108818
    2020-04-30 -0.187426
    Freq: M, dtype: float64
    

    升采样率
    示例: 周数据转为日

    # 周数据
    frame=pd.DataFrame(
    np.random.randn(2,4),
    index=pd.date_range('1/1/2020',periods=2,freq='W-WED'),
    columns=['Colorado','Texa','New York','Ohio']
    )
    # #转为日
    frame.resample('D').asfreq()
    #用前面的值填充
    frame.resample('D').ffill()
    #用后面的值填充
    frame.resample('D').bfill()
    

    八、如何格式化时间序列

    可以使用strftime格式化为相应的字符串,具体方法可以参考Series的API文档的Datetime操作

    x=pd.date_range('2020-01-01',periods=30)
    x.strftime('%Y-%m')
    

  • 相关阅读:
    C++ malloc 和 new 的函数说明
    C++ const 和static的总结以及使用
    动态库与静态库的区别
    C++引用和指针的区别
    gdb的调试常用命令
    FFMPEG的函数翻译文档
    STL在数组算法的使用
    iOS开发 给Label加下划线、中划线
    更改字符串颜色(长度不确定,有服务器返回)
    iOS 获取键盘高度
  • 原文地址:https://www.cnblogs.com/chenqionghe/p/12237010.html
Copyright © 2020-2023  润新知