7.4 KiB
3.2.8:日期与时间工具
相关知识
Pandas
是为金融模型而创建的,所以拥有一些功能非常强大的日期、时间、带时间索引数据的处理工具。本关卡介绍的日期与时间数据主要包含三类:
- 时间戳:表示某个具体的时间点(例如
2015
年7
月4
日上午 7 点) - 时间间隔与周期:期表示开始时间点与结束时间点之间的时间长度,例如
2015
年(指的是2015
年1
月1
日至2015
年12
月31
日这段时间间隔)。周期通常是指一种特殊形式的时间间隔,每个间隔长度相同,彼此之间不会重叠(例如,以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
是结合了原生Python
和NumPy
的datetime
,用来处理时间序列的基础数据类型如下:
- 针对时间戳数据,
Pandas
提供了Timestamp
类型。它本质上是Python
的原生datetime
类型的替代品,但是在性能更好的numpy.datetime64
类型的基础上创建。对应的索引数据结构是DatetimeIndex
。 - 针对时间周期数据,
Pandas
提供了Period
类型。这是利用numpy.datetime64
类型将固定频率的时间间隔进行编码。对应的索引数据结构是**PeriodIndex
**。 - 针对时间增量或持续时间,
Pandas
提供了Timedelta
类型。Timedelta
是一种代替Python
原生datetime.timedelta
类型的高性能数据结构,同样是基于numpy.timedelta64
类型。对应的索引数据结构是**TimedeltaIndex
**。
最基础的日期 / 时间对象是Timestamp
和DatetimeIndex
。这两种对象可以直接使用,最常用的方法是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
参数实现各种频率的时间间隔序列。