美文网首页
2020-08-06--Pandas-06--时间序列详解

2020-08-06--Pandas-06--时间序列详解

作者: program_white | 来源:发表于2020-08-07 11:36 被阅读0次

    基础概述

    下面列出了 Pandas中 和时间日期相关常用的类以及创建方法。

    备注 创建方法
    Timestamp 时刻数据 to_datetime,Timestamp
    DatetimeIndex Timestamp的索引 to_datetime,date_range,DatetimeIndex
    Period 时期数据 Period
    PeriodIndex Period period_range,PeriodIndex

    Pandas 中关于时间序列最常见的类型就是时间戳(Timestamp)了,创建时间戳的方法有很多种,我们分别来看一看。

    time = pd.Timestamp(2018, 5, 21)
    print(time)
    # 2018-05-21 00:00:00
    time = pd.Timestamp("2018-5-21")
    print(time)
    # 2018-05-21 00:00:00
    

    除了时间戳之外,另一个常见的结构是时间跨度(Period)。

    periods = pd.Period("2018-01")
    print(periods)
    # 2018-01
    periods = pd.Period("2018-05", freq="D")
    print(periods)
    # 2018-05-01
    

    Timestamp 和 Period 可以是索引。将Timestamp 和 Period 作为 Series 或 DataFrame的索引后会自动强制转为为 DatetimeIndex 和 PeriodIndex。

    dates = [pd.Timestamp("2018-05-01"), pd.Timestamp("2018-05-02"), pd.Timestamp("2018-05-03"), pd.Timestamp("2018-05-04")]
    ts = pd.Series(data=["Tom", "Bob", "Mary", "James"], index=dates)
    print(ts)
    # 2018-05-01      Tom
    # 2018-05-02      Bob
    # 2018-05-03     Mary
    # 2018-05-04    James
    # dtype: object
    print(ts.index)
    # DatetimeIndex(['2018-05-01', '2018-05-02', '2018-05-03', '2018-05-04'], dtype='datetime64[ns]', freq=None)
    
    periods = [pd.Period("2018-01"), pd.Period("2018-02"), pd.Period("2018-03"), pd.Period("2018-4")]
    ts = pd.Series(data=["Tom", "Bob", "Mary", "James"], index=periods)
    print(ts)
    # 2018-01      Tom
    # 2018-02      Bob
    # 2018-03     Mary
    # 2018-04    James
    # Freq: M, dtype: object
    print(ts.index)
    # PeriodIndex(['2018-01', '2018-02', '2018-03', '2018-04'], dtype='period[M]', freq='M')
    

    转换时间戳

    你可能会想到,我们经常要和文本数据(字符串)打交道,能否快速将文本数据转为时间戳呢?

    答案是可以的,通过 to_datetime 能快速将字符串转换为时间戳。当传递一个Series时,它会返回一个Series(具有相同的索引)。

    timeSeries = pd.to_datetime(pd.Series(["Jul 31, 2018", "2018-05-10", None]))
    print(timeSeries)
    # 0   2018-07-31
    # 1   2018-05-10
    # 2          NaT
    # dtype: datetime64[ns]
    

    而传递一个list列表的则转换为DatetimeIndex。

    timeList = pd.to_datetime(["2005/11/23", "2010.12.31"])
    print(timeList)
    # DatetimeIndex(['2005-11-23', '2010-12-31'], dtype='datetime64[ns]', freq=None)
    

    unix转换时间戳

    除了可以将文本数据转为时间戳外,还可以将 unix 时间转为时间戳。

    sunixTime = pd.to_datetime([1349720105, 1349806505, 1349892905], unit="s")
    print(sunixTime)
    # DatetimeIndex(['2012-10-08 18:15:05', '2012-10-09 18:15:05',
    #                '2012-10-10 18:15:05'],
    #               dtype='datetime64[ns]', freq=None)
    
    msunixTime = pd.to_datetime([1349720105100, 1349720105200, 1349720105300], unit="ms")
    print(msunixTime)
    # DatetimeIndex(['2012-10-08 18:15:05.100000', '2012-10-08 18:15:05.200000',
    #                '2012-10-08 18:15:05.300000'],
    #               dtype='datetime64[ns]', freq=None)
    

    unix的单位可以是s,也可以是ms。该数值是从1970-1-1日开始计算的,通常获取时间最先获取的数值就是unix值,所以用的还是比较多的。

    生成时间戳范围

    有时候,我们可能想要生成某个范围内的时间戳。例如,我想要生成 "2018-6-26" 这一天之后的8天时间戳,如何完成呢?我们可以使用 date_range 和 bdate_range 来完成时间戳范围的生成。

    • date_range 默认使用的频率是 日历日
    • bdate_range 默认使用的频率是 营业日
    data_range = pd.date_range("2018-6-26", periods=8)
    print(data_range)
    # DatetimeIndex(['2018-06-26', '2018-06-27', '2018-06-28', '2018-06-29',
    #                '2018-06-30', '2018-07-01', '2018-07-02', '2018-07-03'],
    #               dtype='datetime64[ns]', freq='D')
    
    bdate_range = pd.bdate_range("2018-6-26", periods=8)
    print(bdate_range)
    # DatetimeIndex(['2018-06-26', '2018-06-27', '2018-06-28', '2018-06-29',
    #                '2018-07-02', '2018-07-03', '2018-07-04', '2018-07-05'],
    #               dtype='datetime64[ns]', freq='B')
    

    当然了,我们可以自己指定频率.

    比如,我们可以按周来生成时间戳范围。

    week = pd.date_range("2018-6-26", periods=8, freq="W")
    print(week)
    # DatetimeIndex(['2018-07-01', '2018-07-08', '2018-07-15', '2018-07-22',
    #                '2018-07-29', '2018-08-05', '2018-08-12', '2018-08-19'],
    #               dtype='datetime64[ns]', freq='W-SUN')
    

    显示的是7-01后的每周的周日。

    DataTimeIndex---时间索引

    在上边,当Timestamp 和 Period 作为 Series 或 DataFrame的索引后会自动强制转为为 DatetimeIndex 和 PeriodIndex。

    所以DatetimeIndex 的主要作用是之一是用作 Pandas 对象的索引,使用它作为索引除了拥有普通索引对象的所有基本功能外,还拥有简化频率处理的高级时间序列方法。

    首先创建一个时间戳作为索引的Series对象

    # 创建时间戳作为索引的Series对象
    rng = pd.date_range("2018-6-24", periods=4, freq="W")
    ts = pd.Series(range(len(rng)), index=rng)
    print(ts)
    # 2018-06-24    0
    # 2018-07-01    1
    # 2018-07-08    2
    # 2018-07-15    3
    # Freq: W-SUN, dtype: int64
    

    访问数据

    通过日期访问数据

    data  =ts['2018-06-24']
    print(data)      # 0
    
    切片访问

    切片操作时前开后开的。

    data1 = ts["2018-07-08": "2018-07-22"]
    print(data1)
    # 2018-07-08    2
    # 2018-07-15    3
    # Freq: W-SUN, dtype: int64
    print(type(data1))
    # <class 'pandas.core.series.Series'>
    

    返回的是Series对象类型。

    年份访问

    data2 = ts['2018']
    print(data2)
    # 2018-06-24    0
    # 2018-07-01    1
    # 2018-07-08    2
    # 2018-07-15    3
    # Freq: W-SUN, dtype: int64
    

    会把该年份中的所有数据全部查出来。

    使用datetime类型进行 数据访问

    除了可以使用字符串对 DateTimeIndex 进行索引外,还可以使用 datetime(日期时间)对象来进行索引。

    from datetime import datetime
    
    c = ts[datetime(2018, 7, 8) : datetime(2018, 7, 22)]
    print(c)
    # 2018-07-08    2
    # 2018-07-15    3
    # Freq: W-SUN, dtype: int64
    

    根据DateTimeIndex或Timestamp访问属性

    我们可以通过 TimestampDateTimeIndex 访问一些时间/日期的属性。这里列举一些常见的,想要查看所有的属性见官方链接:Time/Date Components(http://pandas.pydata.org/pandas-docs/stable/timeseries.html#time-date-components)

    获取所有数据的年份:

    year = ts.index.year
    print(year)
    # Int64Index([2018, 2018, 2018, 2018], dtype='int64')
    

    获取索引是星期几

    week = ts.index.dayofweek
    print(week)
    # Int64Index([6, 6, 6, 6], dtype='int64')
    

    获取一年中的第几周

    weeknum = ts.index.isocalendar()
    print(weeknum)
    #             year  week  day
    # 2018-06-24  2018    25    7
    # 2018-07-01  2018    26    7
    # 2018-07-08  2018    27    7
    # 2018-07-15  2018    28    7
    

    DateOffset对象

    DateOffset 从名称中就可以看出来是要做日期偏移的,
    工作方式如下:

    from pandas.tseries.offsets import *
    d = pd.Timestamp("2018-06-25")
    d = d + DateOffset(weeks=2, days=5)
    print(d)
    # 2018-07-14 00:00:00
    

    除了可以使用 DateOffset 完成上面的功能外,还可以使用偏移量实例来完成。

    print(d)
    # 2018-07-14 00:00:00
    
    d = d + Week(2) + Day(5)
    print(d)
    # 2018-08-02 00:00:00
    

    与时间序列相关的方法

    在做时间序列相关的工作时,经常要对时间做一些移动/滞后、频率转换、采样等相关操作,我们来看下这些操作如何使用吧。

    1.移动

    如果你想移动或滞后时间序列的数据部分,你可以使用 shift 方法。

    ts = ts.shift(2)
    print(ts)
    # 2018-06-24    NaN
    # 2018-07-01    NaN
    # 2018-07-08    0.0
    # 2018-07-15    1.0
    # Freq: W-SUN, dtype: float64
    

    可以看到,Series 所有的值都都移动了 2 个距离。如果不想移动值,而是移动日期索引,可以使用 freq 参数

    c = ts.shift(2,freq=Day())
    print(c)
    # 2018-06-26    0
    # 2018-07-03    1
    # 2018-07-10    2
    # 2018-07-17    3
    # dtype: int64
    

    可以看到,现在日期索引移动了 2 天的间隔。通过 tshift 同样可以达到相同的效果。

    c = ts.tshift(2,freq=Day())
    print(c)
    # 2018-06-26    0
    # 2018-07-03    1
    # 2018-07-10    2
    # 2018-07-17    3
    # dtype: int64
    

    但是建议使用shift()进行移动。

    2.频率转换

    asfrea()

    频率转换可以使用 asfreq 函数来实现。下面演示了将频率由周转为了天。

    print(ts)
    # 2018-06-24    0
    # 2018-07-01    1
    # 2018-07-08    2
    # 2018-07-15    3
    # Freq: W-SUN, dtype: int64
    ts = ts.asfreq(Day())
    print(ts)
    # 2018-06-24    0.0
    # 2018-06-25    NaN
    # 2018-06-26    NaN
    # 2018-06-27    NaN
    # 2018-06-28    NaN
    # 2018-06-29    NaN
    # 2018-06-30    NaN
    # 2018-07-01    1.0
    # 2018-07-02    NaN
    # 2018-07-03    NaN
    # 2018-07-04    NaN
    # 2018-07-05    NaN
    # 2018-07-06    NaN
    # 2018-07-07    NaN
    # 2018-07-08    2.0
    # 2018-07-09    NaN
    # 2018-07-10    NaN
    # 2018-07-11    NaN
    # 2018-07-12    NaN
    # 2018-07-13    NaN
    # 2018-07-14    NaN
    # 2018-07-15    3.0
    # Freq: D, dtype: float64
    

    聪明的你会发现出现了缺失值,因此 Pandas 为你提供了 method 参数来填充缺失值。几种不同的填充方法参考 Pandas 缺失值处理)) 中 fillna 介绍。

    print(ts)
    # 2018-06-24    0
    # 2018-07-01    1
    # 2018-07-08    2
    # 2018-07-15    3
    # Freq: W-SUN, dtype: int64
    ts = ts.asfreq(Day(),method='ffill')
    print(ts)
    # 2018-06-24    0
    # 2018-06-25    0
    # 2018-06-26    0
    # 2018-06-27    0
    # 2018-06-28    0
    # 2018-06-29    0
    # 2018-06-30    0
    # 2018-07-01    1
    # 2018-07-02    1
    # 2018-07-03    1
    # 2018-07-04    1
    # 2018-07-05    1
    # 2018-07-06    1
    # 2018-07-07    1
    # 2018-07-08    2
    # 2018-07-09    2
    # 2018-07-10    2
    # 2018-07-11    2
    # 2018-07-12    2
    # 2018-07-13    2
    # 2018-07-14    2
    # 2018-07-15    3
    # Freq: D, dtype: int64
    

    重采样

    resample 表示根据日期维度进行数据聚合,可以按照分钟、小时、工作日、周、月、年等来作为日期维度,更多的日期维度见 Offset Aliases(http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases)。

    这里我们先以月来作为时间维度来进行聚合。

    求出每个月和每周数据的总和:

    print(c)
    # 2018-06-24    0
    # 2018-06-25    0
    # 2018-06-26    0
    # 2018-06-27    0
    # 2018-06-28    0
    # 2018-06-29    0
    # 2018-06-30    0
    # 2018-07-01    1
    # 2018-07-02    1
    # 2018-07-03    1
    # 2018-07-04    1
    # 2018-07-05    1
    # 2018-07-06    1
    # 2018-07-07    1
    # 2018-07-08    2
    # 2018-07-09    2
    # 2018-07-10    2
    # 2018-07-11    2
    # 2018-07-12    2
    # 2018-07-13    2
    # 2018-07-14    2
    # 2018-07-15    3
    # Freq: D, dtype: int64
    
    re = c.resample('1M').sum()
    print(re)
    # 2018-06-30     0
    # 2018-07-31    24
    # Freq: M, dtype: int64
    
    re = c.resample('1W').sum()
    print(re)
    # 2018-06-24     0
    # 2018-07-01     1
    # 2018-07-08     8
    # 2018-07-15    15
    # Freq: W-SUN, dtype: int64
    

    求出每个月和每周数据的平均值:

    re = c.resample("1M").mean()
    print(re)
    # 2018-06-30    0.0
    # 2018-07-31    1.6
    # Freq: M, dtype: float64
    
    re = c.resample("1W").mean()
    print(re)
    # 2018-06-24    0.000000
    # 2018-07-01    0.142857
    # 2018-07-08    1.142857
    # 2018-07-15    2.142857
    # Freq: W-SUN, dtype: float64
    

    相关文章

      网友评论

          本文标题:2020-08-06--Pandas-06--时间序列详解

          本文链接:https://www.haomeiwen.com/subject/kgyzrktx.html