Pandas 时间序列

為{幸葍}努か 提交于 2019-12-03 23:15:31
# 导入相关库 
import numpy as np 
import pandas as pd

在做金融领域方面的分析时,经常会对时间进行一系列的处理。Pandas 内部自带了很多关于时间序列相关的工具,所以它非常适合处理时间序列。在处理时间序列的过程中,我们经常会去做以下一些任务:

  • 生成固定频率日期和时间跨度的序列
  • 将时间序列整合或转换为特定频率
  • 基于各种非标准时间增量(例如,在一年的最后一个工作日之前的 5 个工作日)计算“相对”日期,或向前或向后“滚动”日期 

使用 Pandas 可以轻松完成以上任务

基础概述

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

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

 

 

 

 

 

 

  

 

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

时间戳(Timestamp)

pd.Timestamp(2019, 11, 7)   # Timestamp('2019-11-07 00:00:00')
pd.Timestamp("2019-11-7")   # Timestamp('2019-11-07 00:00:00')
pd.to_datetime("2019-11-7")  # Timestamp('2019-11-07 00:00:00')

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

时间跨度(Period)

  freq 为频率周期参数,D 为日,M 为月 

pd.Period("2019-11")   # Period('2019-11', 'M')
pd.Period("2019-11-7")   # Period('2019-11-07', 'D')
pd.Period("2019-11", freq="D")   # Period('2019-11-01', 'D')

基于时间的索引

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

  Timestamp 作为索引

dates = [  pd.Timestamp("2019-11-01"),   pd.Timestamp("2019-11-02"),   pd.Timestamp("2019-11-03"),   pd.Timestamp("2019-11-04")] 
ts = pd.Series(data=["Tom", "Bob", "Mary", "James"], index=dates) 
ts
"""
2018-05-01      Tom
2018-05-02      Bob
2018-05-03     Mary
2018-05-04    James
dtype: object
"""
ts.index 
"""
DatetimeIndex(['2018-05-01', '2018-05-02', '2018-05-03', '2018-05-04'], dtype='datetime64[ns]', freq=None)
"""

  Period 作为索引

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) 
ts
"""
2018-01      Tom
2018-02      Bob
2018-03     Mary
2018-04    James
Freq: M, dtype: object
"""
ts.index 
"""
PeriodIndex(['2018-01', '2018-02', '2018-03', '2018-04'], dtype='period[M]', freq='M')
"""

转换时间戳

  你可能会想到,我们经常要和文本数据(字符串)打交道,能否快速将文本数据转为时间戳呢?答案是可以的,通过 to_datetime 能快速将字符串转换为时间戳。当传递一个Series时,它会返 回一个Series(具有相同的索引),而类似列表的则转换为 DatetimeIndex

to_datetime 将字符串转换为时间戳

pd.to_datetime(pd.Series(["Jul 31, 2019", "2019-11-10", None])) 
"""
0   2019-07-31
1   2019-11-10
2          NaT
dtype: datetime64[ns]
"""

pd.to_datetime(["2008/8/28", "2008.9.25"])
"""
DatetimeIndex(['2008-08-28', '2008-09-25'], dtype='datetime64[ns]', freq=None)
"""

将 unix 时间转为时间戳

pd.to_datetime([1349720105, 1349806505, 1349892905], unit="s")
"""
DatetimeIndex(['2012-10-08 18:15:05', '2012-10-09 18:15:05',
               '2012-10-10 18:15:05'],
              dtype='datetime64[ns]', freq=None)
"""

pd.to_datetime([1349720105100, 1349720105200, 1349720105300], unit="ms")
"""
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)
"""

 

生成时间戳范围

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

生成某个范围内的时间戳

  date_range 默认使用的频率是日历日

  bdate_range 默认使用的频率是营业日

pd.date_range("2019-10-1", periods=7) 
"""
DatetimeIndex(['2019-10-01', '2019-10-02', '2019-10-03', '2019-10-04',
               '2019-10-05', '2019-10-06', '2019-10-07'],
              dtype='datetime64[ns]', freq='D')
"""

pd.bdate_range("2019-10-1", periods=7) 
"""
DatetimeIndex(['2019-10-01', '2019-10-02', '2019-10-03', '2019-10-04',
               '2019-10-07', '2019-10-08', '2019-10-09'],
              dtype='datetime64[ns]', freq='B')
"""

按周来生成时间戳范围

pd.date_range("2019-10-1", periods=7, freq="W")
"""
DatetimeIndex(['2019-10-06', '2019-10-13', '2019-10-20', '2019-10-27',
               '2019-11-03', '2019-11-10', '2019-11-17'],
              dtype='datetime64[ns]', freq='W-SUN')
"""

DatetimeIndex

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

rng = pd.date_range("2019-10-1", periods=4, freq="W") 
ts = pd.Series(range(len(rng)), index=rng) 
ts
"""
2019-10-06    0
2019-10-13    1
2019-10-20    2
2019-10-27    3
Freq: W-SUN, dtype: int64
"""

通过日期访问数据

ts["2019-10-20"]  # 2

通过日期区间访问数据切片

ts["2019-10-13": "2019-10-20"]
"""
2019-10-13    1
2019-10-20    2
Freq: W-SUN, dtype: int64
"""

传入年份

ts["2019"]

传入年份和月份

ts["2019-10"]

datetime 进行索引

from datetime import datetime 
ts[datetime(2019, 10, 6) : datetime(2019, 10, 13)]

获取年份

ts.index.year

获取星期几

ts.index.dayofweek

获取一年中的第几个星期

ts.index.weekofyear 

DateOffset 对象

  DateOffset 是做日期偏移的,它的参数与 dateutil.relativedelta 基 本相同,工作方式如下:

from pandas.tseries.offsets import *
d = pd.Timestamp("2019-10-06") 
d + DateOffset(weeks=2, days=5) 
"""
Timestamp('2019-10-25 00:00:00')
"""

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

from pandas.tseries.offsets import *
d = pd.Timestamp("2019-10-06") 
d + Week(2) + Day(5) 

与时间序列相关的方法

  在做时间序列相关的工作时,经常要对时间做一些移动/滞后、频率转换、采样等相关操作。

移动时间序列 

  如果你想移动或滞后时间序列,你可以使用  shift  方法

ts.shift(2) 
"""
2019-10-06    NaN
2019-10-13    NaN
2019-10-20    0.0
2019-10-27    1.0
Freq: W-SUN, dtype: float64
"""

  可以看到,Series 所有的值都都移动了 2 个距离。如果不想移动值,而是移动日期索引,可以使 用  freq  参数,它可以接受一个  DateOffset  类或其他  timedelta  类对象或一个 offset 别名

ts.shift(2, freq=Day())
"""
2019-10-08    0
2019-10-15    1
2019-10-22    2
2019-10-29    3
Freq: W-TUE, dtype: int64
"""

  通过 tshift 同样可以达到相同的效果: 

ts.tshift(2, freq=Day()) 

频率转换 

  频率转换可以使用 asfreq 函数来实现

# 将频率由周转为了天
ts.asfreq(Day()) 

  但是我们发现出现了缺失值,因此 Pandas 提供了 method 参数来填充缺失值。几种不同的填充方法参考 Pandas 缺失值处理 中 fillna 介绍。 

ts.asfreq(Day(), method="pad")

重采样

  resample 表示根据日期维度进行数据聚合,可以按照分钟、小时、工作日、周、月、年等来作为日期维度

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

# 求出每个月的数值之和
 ts.resample("1M").sum()

# 求出每个月的数值平均值 
ts.resample("1M").mean()

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!