You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

7.4 KiB

3.2.8:日期与时间工具

相关知识

Pandas是为金融模型而创建的,所以拥有一些功能非常强大的日期、时间、带时间索引数据的处理工具。本关卡介绍的日期与时间数据主要包含三类:

  • 时间戳:表示某个具体的时间点(例如201574日上午 7 点)
  • 时间间隔与周期:期表示开始时间点与结束时间点之间的时间长度,例如2015年(指的是201511日至20151231日这段时间间隔)。周期通常是指一种特殊形式的时间间隔,每个间隔长度相同,彼此之间不会重叠(例如,以24小时为周期构成每一天)
  • 时间增量或持续时间:表示精确的时间长度(例如,某程序运行持续时间22.56秒)

Python 的日期与时间工具

原生Python中也有处理日期与时间的工具,它与Pandas中处理时间的工具有着千丝万缕的联系。Python的日期与时间功能都在标准库的datetime模块和第三方库dateutil模块。如果你处理的时间数据量比较大,那么速度就会比较慢,这时就需要使用到NumPy中已经被编码的日期类型数组了。

NumPy中的datetime64类型

Python原生日期格式的性能弱点促使NumPy团队为NumPy增加了自己的时间序列类型。datetime64类型将日期编码为64位整数,这样可以让日期数组非常紧凑(节省内存)。

In[3]import numpy as np 
 	  date = np.array('2015-07-04', dtype=np.datetime64) 
 	  date 
Out[3]array(datetime.date(2015, 7, 4), dtype='datetime64[D]')

有了这个日期格式,既可以进行快速的向量化运算:

In[4]date + np.arange(12) #由于date是datetime类型所以向量化运算也是datetime类型的运算
Out[4]
array(['2015-07-04', '2015-07-05', '2015-07-06', '2015-07-07', '2015-07-08', '2015-07-09', '2015-07-10', '2015-07-11', '2015-07-12', '2015-07-13', '2015-07-14', '2015-07-15'], dtype='datetime64[D]')

由于datetime64对象是64位精度,所以可编码的时间范围可以是基本单元的 264倍。也就是说,datetime64时间精度最大时间跨度之间达成了一种平衡,也就是说,NumPy会自动判断输入时间所需要使用的时间单位。

In[5]: np.datetime64('2015-07-04') # 天为单位
Out[5]: numpy.datetime64('2015-07-04')
In[6]: np.datetime64('2015-07-04 12:00') # 分钟为单位
Out[6]: numpy.datetime64('2015-07-04T12:00')
In[7]: np.datetime64('2015-07-04 12:59:59.50', 'ns') # 手动设置时间单位
Out[7]: numpy.datetime64('2015-07-04T12:59:59.500000000')

日期与时间单位格式代码表如下:

代码 含义 时间跨度(相对) 时间跨度(绝对)
Y year ± 9.2e18 年 [9.2e18 BC, 9.2e18 AD]
M month ± 7.6e17 年 [7.6e17 BC, 7.6e17 AD]
W week ± 1.7e17 年 [1.7e17 BC, 1.7e17 AD]
D day ± 2.5e16 年 [2.5e16 BC, 2.5e16 AD]
h hour ± 1.0e15 年 [1.0e15 BC, 1.0e15 AD]
m minute ± 1.7e13 年 [1.7e13 BC, 1.7e13 AD]
s second ± 2.9e12 年 [ 2.9e9 BC, 2.9e9 AD]
ms 毫秒millisecond ± 2.9e9 年 [ 2.9e6 BC, 2.9e6 AD]
us 微秒microsecond ± 2.9e6 年 [290301 BC, 294241 AD]
ns 纳秒nanosecond ± 292 年 [ 1678 AD, 2262 AD]
ps 皮秒picosecond ± 106 天 [ 1969 AD, 1970 AD]
fs 飞秒femtosecond ± 2.6 小时 [ 1969 AD, 1970 AD]
as 原秒attosecond ± 9.2 秒 [ 1969 AD, 1970 AD

Pandas的日期与时间工具

Pandas中的datetime是结合了原生PythonNumPydatetime,用来处理时间序列的基础数据类型如下:

  • 针对时间戳数据,Pandas提供了Timestamp类型。它本质上是Python的原生datetime类型的替代品,但是在性能更好的numpy.datetime64类型的基础上创建。对应的索引数据结构是 DatetimeIndex
  • 针对时间周期数据,Pandas提供了Period类型。这是利用numpy.datetime64类型将固定频率的时间间隔进行编码。对应的索引数据结构是**PeriodIndex**。
  • 针对时间增量或持续时间,Pandas提供了Timedelta类型。Timedelta是一种代替Python原生datetime.timedelta类型的高性能数据结构,同样是基于numpy.timedelta64类型。对应的索引数据结构是**TimedeltaIndex**。

最基础的日期 / 时间对象是TimestampDatetimeIndex。这两种对象可以直接使用,最常用的方法是pd.to_datetime()函数,。对pd.to_datetime() 传递一个日期会返回一个Timestamp类型,传递一个时间序列会返回一个DatetimeIndex类型

  • **DatetimeIndex**类型
In[8]dates = pd.to_datetime([datetime(2015, 7, 3), '4th of July, 2015', '2015-Jul-6', '07-07-2015', '20150708']) 
 		dates
Out[8]DatetimeIndex(['2015-07-03', '2015-07-04', '2015-07-06', '2015-07-07', '2015-07-08'], dtype='datetime64[ns]', freq=None)
  • **PeriodIndex**类型 任何DatetimeIndex类型都可以通过to_period()方法和一个频率代码转换成PeriodIndex类型,PeridoIndex类型可以通过to_timestamp()方法转换为DatetimeIndex类型。下面用D将数据转换成单日的时间序列:
In[10]: dates.to_period('D')
Out[10]: PeriodIndex(['2015-07-03', '2015-07-04', '2015-07-06', '2015-07-07', '2015-07-08'], dtype='int64', freq='D')
  • **TimedeltaIndex**类型 当用一个日期减去另一个日期时,返回的结果是TimedeltaIndex类型:
In[11]: dates - dates[0] 
Out[11]: 
TimedeltaIndex(['0 days', '1 days', '3 days', '4 days', '5 days'], dtype='timedelta64[ns]', freq=None)

为了能更简便地创建有规律的时间序列,Pandas提供了一些方法:pd.date_range()可以处理时间戳、pd.period_range()可以处理周期、pd.timedelta_range()可以处理时间间隔。

  • pd.date_range() 通过开始日期、结束日期和频率代码(可选的)创建一个有规律的日期序列,默认的频率是天:
In[12]pd.date_range('2015-07-03', '2015-07-10')
Out[12]DatetimeIndex(['2015-07-03', '2015-07-04', '2015-07-05', '2015-07-06', '2015-07-07', '2015-07-08', '2015-07-09', '2015-07-10'], dtype='datetime64[ns]', freq='D')

范围不一定非是开始时间和结束时间,也可以设置周期数periods来达到改目的:

In[13]pd.date_range('2015-07-03', periods=8) 
Out[13]DatetimeIndex(['2015-07-03', '2015-07-04', '2015-07-05', '2015-07-06', '2015-07-07', '2015-07-08', '2015-07-09', '2015-07-10'], dtype='datetime64[ns]', freq='D')

freq表示时间间隔,默认是D,可以通过修改它来periods参数的意义:

In[14]pd.date_range('2015-07-03', periods=8, freq='H')
Out[14] 
DatetimeIndex(['2015-07-03 00:00:00', '2015-07-03 01:00:00', 
 				'2015-07-03 02:00:00', '2015-07-03 03:00:00', 
 				'2015-07-03 04:00:00', '2015-07-03 05:00:00', 
 				'2015-07-03 06:00:00', '2015-07-03 07:00:00'], 
 				dtype='datetime64[ns]', freq='H')
  • pd.timedelta_range() 如果要创建一个有规律的周期或时间间隔序列,pd.timedelta_range()可以实现该功能:
In[15]pd.period_range('2015-07', periods=8, freq='M')
Out[15]
PeriodIndex(['2015-07', '2015-08', '2015-09', '2015-10', '2015-11', '2015-12', '2016-01', '2016-02'], dtype='int64', freq='M')

也可以通过修改freq参数实现各种频率的时间间隔序列。