zoukankan      html  css  js  c++  java
  • 6-Pandas时序数据处理(日期范围pd.date_range()、频率(基础频率表)及移动(shift()、rollforward()、rollback()))

    一、生成日期范围的时序数据

    pd.date_range()可用于生成指定长度的日期索引,默认产生按天计算的时间点(即日期范围)。其参数可以是:

    • 起始结束日期
    • 或者是仅有一个起始或结束日期,加上一个时间段参数

    以下三种方法结果一致:

    • pd.date_range('20200801','20200810')
    • pd.date_range(start='20200801',periods=10)
    • pd.date_range(end='20200810',periods=10)

    结果

    DatetimeIndex(['2020-08-01', '2020-08-02', '2020-08-03', '2020-08-04',
                   '2020-08-05', '2020-08-06', '2020-08-07', '2020-08-08',
                   '2020-08-09', '2020-08-10'],
                  dtype='datetime64[ns]', freq='D')

    注意:此处的freq参数表示时间序列数据的频率,其值为D,表示是以天为频率;

    所以,若想生成一个特殊频率的日期索引,若一个由每月最后一个工作日组成的日期索引,直接加上参数freq='BM'(BM表示business end of month)

    >>> pd.date_range('2020-01-01','2020-12-31',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', '2020-12-31'],
                  dtype='datetime64[ns]', freq='BM')
    

    二、日期频率

    pandas中的频率是由一个基础频率和一个乘数组成。基础频率通常以一个字符串别名表示,如'M','H'。

    date_range()参数freq的取值说明

    基础频率表
    别名 偏移量类型 说明
    D Day 每日历日
    B  BusinessDay 每工作日 
    H  Hour 每小时 
    T或min  Minute 每分 
    M  MonthEnd 每月最后一个日历日 
    BM  BusinessMonthEnd  每月最后一个工作日
    WOM-1MON   WeekOfMonth  产生每月第一、第二、第四周的星期几,如WOM-3FRI表示每月第3个周五
    Q-JAN   QuarterEnd  对于指定月份(JAN、FEB、MAR...DEC)结束的年度,每季度最后一个月的最后一个日历日
    A-JAN   YearEnd  对于指定年份的最后一个日历日

      

    :从2020年1月至2020年3月以'3M'的频率生成一个时间范围 

    >>> pd.date_range('2020-01-01','2020-12-31',freq='3M')
    DatetimeIndex(['2020-01-31', '2020-04-30', '2020-07-31', '2020-10-31'], dtype='datetime64[ns]', freq='3M')
    
    >>> pd.date_range('2020-01-01','2020-12-31',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',
                   '2020-09-18', '2020-10-16', '2020-11-20', '2020-12-18'],
                  dtype='datetime64[ns]', freq='WOM-3FRI')
    
    >>> pd.date_range('2020-01-01',periods=3,freq='2H30T')
    DatetimeIndex(['2020-01-01 00:00:00', '2020-01-01 02:30:00',
                   '2020-01-01 05:00:00'],
                  dtype='datetime64[ns]', freq='150T')

      对于每个基础频率,都有一个日期偏移量(date offset)对象与之对应。可以通过实例化日期偏移量来创建某种频率:

    >>> from pandas.tseries.offsets import Hour,Minute
    >>> hour = Hour()
    >>> hour
    <Hour>
    
    >>> four_hours = Hour(4)
    >>> four_hours
    <4 * Hours>
    

      大部分偏移量对象可以通过加法进行连接

    >>> Hour(3)+Minute(20)
    <200 * Minutes>
    

      有些频率所描述的时间点并不是均匀分隔的。例如'M'和'BM'就取决于每月的天数,对于后者,还要考虑月末是否是周末,将这些成为锚点偏移量

    三、移动(超前或之后)数据

    (1)移动(Shifting)指的是沿着时间轴将数据向前或向后移动,保持索引不变

      thift()方法默认表示索引不变数据后移;若提供freq参数,则此时将移动index,数据将保持不变

    #创建一个时序数据
    >>> ts = pd.Series(np.random.randint(0,10,5))
    >>> ts.index = pd.date_range('2020-1-1',periods=5,freq='M')
    >>> ts
    2020-01-31    8
    2020-02-29    5
    2020-03-31    3
    2020-04-30    9
    2020-05-31    4
    Freq: M, dtype: int32
    
    #索引不变,数据向后移2个单位
    >>> ts.shift(2)
    2020-01-31    NaN
    2020-02-29    NaN
    2020-03-31    8.0
    2020-04-30    5.0
    2020-05-31    3.0
    Freq: M, dtype: float64
    
    #索引不变,数据向前移2个单位
    >>> ts.shift(-2)
    2020-01-31    3.0
    2020-02-29    9.0
    2020-03-31    4.0
    2020-04-30    NaN
    2020-05-31    NaN
    Freq: M, dtype: float64
    
    
    #将时间索引向后移2个月,数据保持不变
    >>> ts.shift(2,freq='M')
    2020-03-31    8
    2020-04-30    5
    2020-05-31    3
    2020-06-30    9
    2020-07-31    4
    Freq: M, dtype: int32
    
    #将时间索引向前移2个月,数据保持不变
    >>> ts.shift(-2,freq='M')
    2019-11-30    8
    2019-12-31    5
    2020-01-31    3
    2020-02-29    9
    2020-03-31    4
    

      (2)如何通过偏移量对日期进行位移?

        在时间后直接加上一个实例化的日期偏移量即可。

    >>> from pandas.tseries.offsets import Day,MonthEnd
    >>> from datetime import datetime
    >>> t = datetime(2020,8,8)
    
    >>> t + 10*Day()
    Timestamp('2020-08-18 00:00:00')
    
    #第一次位移量没有一个月那么长,则位移就在当月,所以此时进行2个位移的结果是9月
    >>> t + 2*MonthEnd()
    Timestamp('2020-09-30 00:00:00')
    

      (3)结合锚点偏移量,使用rollforward()和rollback()方法,可以将日期向前或向后滚动

    >>> from pandas.tseries.offsets import MonthEnd,YearEnd,QuarterEnd
    >>> offset = MonthEnd()
    >>> t
    datetime.datetime(2020, 8, 8, 0, 0)
    #向前滚动
    >>> offset.rollforward(t)
    Timestamp('2020-08-31 00:00:00')
    #向后滚动
    >>> offset.rollback(t)
    Timestamp('2020-07-31 00:00:00')
    
    >>> offset1 = YearEnd()
    >>> offset1.rollback(t)
    Timestamp('2019-12-31 00:00:00')
    >>> offset1.rollforward(t)
    Timestamp('2020-12-31 00:00:00')
    
    >>> offset2 = QuarterEnd()
    >>> offset2.rollforward(t)
    Timestamp('2020-09-30 00:00:00')
    

     四、例子

      若有以下时间序列,如何在每月月末显示该月数据的均值?

    >>> import pandas as pd
    >>> import numpy as np
    >>> ts = pd.Series(np.random.randint(0,10,10))
    >>> ts.index = pd.date_range(start='2020-1-15',periods=10,freq='10D')
    >>> ts
    2020-01-15    7
    2020-01-25    1
    2020-02-04    8
    2020-02-14    7
    2020-02-24    1
    2020-03-05    3
    2020-03-15    6
    2020-03-25    8
    2020-04-04    6
    2020-04-14    1
    Freq: 10D, dtype: int32
    

      解法步骤

    1. 先将时间序列使用rollforward()向前滚动,这样将日期索引都设置为当前月的最后一天;
    2. 使用groupby()对时间索引进行分组聚合,求其均值
    >>> from pandas.tseries.offsets import MonthEnd
    >>> offset = MonthEnd()
    #方法一:使用列表推导式将时间序列向后滚动至当前月的最后一天,再将生成的列表转换成DatetimeIndex
    >>> ts.index = pd.to_datetime([offset.rollforward(index) for index in ts.index])
    >>> ts
    2020-01-31    7
    2020-01-31    1
    2020-02-29    8
    2020-02-29    7
    2020-02-29    1
    2020-03-31    3
    2020-03-31    6
    2020-03-31    8
    2020-04-30    6
    2020-04-30    1
    dtype: int32
    
    #使用Groupby()聚合分组
    >>> ts.groupby(ts.index).mean()
    2020-01-31    4.000000
    2020-02-29    5.333333
    2020-03-31    5.666667
    2020-04-30    3.500000
    dtype: float64
    
    #方法二:以下结果与上述结果一致
    >>> ts.groupby(offset.rollforward).mean()
    2020-01-31    4.000000
    2020-02-29    5.333333
    2020-03-31    5.666667
    2020-04-30    3.500000
    dtype: float64

      上述两种方法的区别是方法一改变了ts,方法二没有;若在使用过程中,若想使用方法一又不想改变ts的值,可以先复制一个ts,然后对复制后的ts进行操作即可。

  • 相关阅读:
    mybatis批量插入、批量更新和批量删除
    MySQL本地密码过期处理及永不过期设置
    Intellij IDEA安装与使用,完整详细。
    深入浅出mybatis之useGeneratedKeys参数用法
    springmvc_learn
    Mac下,MySQL数据库中文乱码的解决方法
    springmvc整合mybatis实现商品列表查询
    sql server 数据库导出表里所有数据成insert 语句
    推荐几个bootstrap 后端UI框架
    50个极好的bootstrap框架
  • 原文地址:https://www.cnblogs.com/Cheryol/p/13463730.html
Copyright © 2011-2022 走看看