导入所需模块:
import numpy as np
import pandas as pd
一、时序中的基本对象
时间序列的概念在日常生活中十分常见,但对于一个具体的时序事件而言,可以从多个时间对象的角度来描述。例如2020年9月7日周一早上8点整需要到教室上课,这个课会在当天早上10点结束,其中包含了哪些时间概念?
- 第一,会出现时间戳(Date times)的概念,即’2020-9-7 08:00:00’和’2020-9-7 10:00:00’这两个时间点分别代表了上课和下课的时刻,在
pandas
中称为Timestamp
。同时,一系列的时间戳可以组成DatetimeIndex
,而将它放到Series
中后,Series
的类型就变为了datetime64[ns]
,如果有涉及时区则为datetime64[ns, tz]
,其中tz是timezone的简写。 - 第二,会出现时间差(Time deltas)的概念,即上课需要的时间,两个
Timestamp
做差就得到了时间差,pandas中利用Timedelta
来表示。类似的,一系列的时间差就组成了TimedeltaIndex
, 而将它放到Series
中后,Series
的类型就变为了timedelta64[ns]
。 - 第三,会出现时间段(Time spans)的概念,即在8点到10点这个区间都会持续地在上课,在
pandas
利用Period
来表示。类似的,一系列的时间段就组成了PeriodIndex
, 而将它放到Series
中后,Series
的类型就变为了Period
。 - 第四,会出现日期偏置(Date offsets)的概念,假设你只知道9月的第一个周一早上8点要去上课,但不知道具体的日期,那么就需要一个类型来处理此类需求。再例如,想要知道2020年9月7日后的第30个工作日是哪一天,那么时间差就解决不了你的问题,从而
pandas
中的DateOffset
就出现了。同时,pandas
中没有为一列时间偏置专门设计存储类型,理由也很简单,因为需求比较奇怪,一般来说我们只需要对一批时间特征做一个统一的特殊日期偏置。
通过这个简单的例子,就能够容易地总结出官方文档中的这个表格:
概念 | 单元素类型 | 数组类型 | pandas数据类型 |
---|---|---|---|
Date times | Timestamp |
DatetimeIndex |
datetime64[ns] |
Time deltas | Timedelta |
TimedeltaIndex |
timedelta64[ns] |
Time spans | Period |
PeriodIndex |
period[freq] |
Date offsets | DateOffset |
None |
None |
由于时间段对象Period/PeriodIndex
的使用频率并不高,因此将不进行讲解,而只涉及时间戳序列、时间差序列和日期偏置的相关内容。
二、时间戳
1. Timestamp的构造与属性
单个时间戳的生成利用pd.Timestamp
实现,一般而言的常见日期格式都能被成功地转换:
ts = pd.Timestamp('2020/1/1')
ts
#Timestamp('2020-01-01 00:00:00')
ts = pd.Timestamp('2020-1-1 08:10:30')
ts
#Timestamp('2020-01-01 08:10:30')
通过year, month, day, hour, min, second
可以获取具体的数值:
在pandas
中,时间戳的最小精度为纳秒ns
,由于使用了64位存储,可以表示的时间范围大约可以如下计算:
T i m e R a n g e = 2 64 1 0 9 × 60 × 60 × 24 × 365 ≈ 585 ( Y e a r s ) \rm Time\,Range = \frac{2^{64}}{10^9\times 60\times 60\times 24\times 365} \approx 585 (Years) TimeRange=109×60×60×24×365264≈585(Years)
通过pd.Timestamp.max
和pd.Timestamp.min
可以获取时间戳表示的范围,可以看到确实表示的区间年数大小正如上述计算结果:
2. Datetime序列的生成
一组时间戳可以组成时间序列,可以用to_datetime
和date_range
来生成。其中,to_datetime
能够把一列时间戳格式的对象转换成为datetime64[ns]
类型的时间序列:
在极少数情况,时间戳的格式不满足转换时,可以强制使用format
进行匹配:
temp = pd.to_datetime(['2020\\1\\1','2020\\1\\3'],format='%Y\\%m\\%d')
temp
# DatetimeIndex(['2020-01-01', '2020-01-03'], dtype='datetime64[ns]', freq=None)
注意上面由于传入的是列表,而非pandas
内部的Series
,因此返回的是DatetimeIndex
,如果想要转为datetime64[ns]
的序列,需要显式用Series
转化:
pd.Series(temp).head()
'''
0 2020-01-01
1 2020-01-03
dtype: datetime64[ns]
'''
另外,还存在一种把表的多列时间属性拼接转为时间序列的to_datetime
操作,此时的列名必须和以下给定的时间关键词列名一致(传入的是df):
df_date_cols = pd.DataFrame({
'year': [2020, 2020],
'month': [1, 1],
'day': [1, 2],
'hour': [10, 20],
'minute': [30, 50],
'second': [20, 40]})
pd.to_datetime(df_date_cols)
0 2020-01-01 10:30:20
1 2020-01-02 20:50:40
dtype: datetime64[ns]
date_range
是一种生成连续间隔时间的一种方法,其重要的参数为start, end, freq, periods
,它们分别表示开始时间,结束时间,时间间隔,时间戳个数。其中,四个中的三个参数决定了,那么剩下的一个就随之确定了。这里要注意,开始或结束日期如果作为端点则它会被包含:
这里的freq
参数与DateOffset
对象紧密相关,将在第四节介绍其具体的用法。
【练一练1】
Timestamp
上定义了一个value
属性,其返回的整数值代表了从1970年1月1日零点到给定时间戳相差的纳秒数,请利用这个属性构造一个随机生成给定日期区间内日期序列的函数。
【解答】
这里用的是numpy的生成随机数的方法