pandas之date_range详细说明 郝伟 2021/06/11 [TOC]
1. 简介
在对二维数据进行处理时,时间序列是经常使用的一种数据类型。在pandas中,我们可以使用 pandas.date_range() 函数对数据建立时间相关的索引。在建立的过程中,需要注意以下几点:
pandas.date_range
函数是比较重要核心的内容,用于生成DatetimeIndex的对象;- 支持 datetime 对象表示的时间;
pandas 支持 4 种常见时间概念(参考资料):
- 日期时间(Datetime):带时区的日期时间,类似于标准库的 datetime.datetime。
- 时间差(Timedelta):绝对时间周期,类似于标准库的 datetime.timedelta。
- 时间段(Timespan):在某一时点以指定频率定义的时间跨度。
- 日期偏移(Dateoffset):与日历运算对应的时间段,类似于 dateutil 的 dateutil.relativedelta.relativedelta。
2. 关于时间分段的三个相关概念
分段的原理是在给定的时间段时,划分出若干个时间点。在这个过程中,分段涉及了三个关键要素:
- 时间点:某个具体的时刻,如 18:35:25,相当于坐标轴上的某个值;
- 时间段:在指定的两个时间点间的所有时间点,代表的是连续的一个时间范围,如上午9点到下午6点。在数学上可以表示为 $[t_s, t_e]$,在时间 $t_s$ 和 $t_e$ 之间的范围。再次强调,时间段是一个连续的范围,包括无数个时间点。
- 时间长度:两个时间点的间隔,相当于 $|t_e - t_s|$。时间间隔可以理解为是一个长度单位,表达的是两个时间点的间隔的长度。时间间隔就是一个时间长度的概念。
比较常用的一种方式就是date_range根据输入的时间范围和时间间隔,返回的是一序列的时间点。举例来说,“今天工作时间每小时的整点记录一次数据”。在这里的时间范围即是工作时间,比如说早九晚五就是从上午9点至下午17点的时间范围,这个时间范围对应的时间长度是8个小时,那么可以返回的时间点序列就是 [9:00, 10:00, 11:00, 12:00, 13:00, 14:00, 15:00, 16:00, 17:00] 共九个点。
实际上很多时候,时间范围进行分段并不是一件简单的事情,在分段的过程中,会因为不同的情况导致不同的结果。比如 “从 12:30 到 15:40,每小时记录一次数据” 和 “从 12:30 到 15:40,每个整点记录一次数据”,所表达的就是不同的内容,返回的结果分别是 [12:30, 13:30, 14:30, 15:30] 和 [13:00, 14:00, 15:00]。可以发现返回的时候不仅时间点不一样,结果的数量也不一样。由于在分段时,具体到时分秒时间间隔比较小,所以影响相对小些,如果是年月则会影响很大。比如,“某公司从每月15日要做一次数据报表,那么从2019/07/26成立到2021/05/20,一共做了多少次报表?”。类似这样的问题都需要有相应的计算方法或工具,因此,pandas 提供了相当多的 freq 类型以处理这些情况。
3. 基本语法
如下所示:
pandas.date_range(
start=None, # 开始时间
end=None, # 结束时间
periods=None, # 时间范围长度,基于 freq 的整数个单位
freq='D', # 参见下文
tz=None,
normalize=False, # 未知
name=None, # 序列的名称
closed=None, # 见下面文档
**kwargs)
主要参数说明:
- start: 开始时间点;
- end: 结束时间
- periods:周期长度,取值为整数或None
- freq:日期偏移量,取值为string或DateOffset,默认为'D', 详细的列表参见这里,以下会详细说明;
- normalize:若参数为True表示将start、end参数值正则化到午夜时间戳
- name:生成时间索引对象的名称,取值为string或None
- closed:可以理解成在closed=None情况下返回的结果中,若closed=‘left’表示在返回的结果基础上,再取左开右闭的结果,若closed='right'表示在返回的结果基础上,再取做闭右开的结果
4. date_range 函数示例
date_range 函数常用的两种类型:
4.1. 根据开始时间点和间隔数生成时间点序列
根据开始时间,以一定的时间间隔,生成指定个时间点。这是相对比较容易理解的一种时间点序列的生成方式,比如:
import pandas as pd
import datetime
dr1 = pd.date_range(start='1981-07-13', periods=14580)
print(len(dr1), dr1)
14580 DatetimeIndex(['1981-07-13', '1981-07-14', '1981-07-15', '1981-07-16',
'1981-07-17', '1981-07-18', '1981-07-19', '1981-07-20',
'1981-07-21', '1981-07-22',
...
'2021-06-03', '2021-06-04', '2021-06-05', '2021-06-06',
'2021-06-07', '2021-06-08', '2021-06-09', '2021-06-10',
'2021-06-11', '2021-06-12'],
dtype='datetime64[ns]', length=14580, freq='D')
4.2. 根据开始时间点和时间间隔生成时间点序列
在指定的时间范围内,以固定的时间点,生成相应的时间点序列,如下所示。
import pandas as pd
import datetime
dr2 = pd.date_range(start='1981-07-13', end='2021-06-11')
print(len(dr2), dr2)
14579 DatetimeIndex(['1981-07-13', '1981-07-14', '1981-07-15', '1981-07-16',
'1981-07-17', '1981-07-18', '1981-07-19', '1981-07-20',
'1981-07-21', '1981-07-22',
...
'2021-06-02', '2021-06-03', '2021-06-04', '2021-06-05',
'2021-06-06', '2021-06-07', '2021-06-08', '2021-06-09',
'2021-06-10', '2021-06-11'],
dtype='datetime64[ns]', length=14579, freq='D')
5. freq 详细说明
在 date_range 函数中,freq 是最为复杂的一个参数,不仅数量多,而且很多概念不是很直观易理解,所以本章结合代码,进行详细说明。
5.1. freq 中的 start 和 end
在选择单位的时候,由于年、季和月的跨度时间很大,所以需要指定某一天为分隔点,从而能够确定分隔的时间段。所以在freq中有大量的 start 和 end 的区别。让我们先看以下示例。
import pandas as pd
import datetime
start = datetime.datetime(2019, 1, 1)
end = datetime.datetime(2021, 06, 11)
dr1 = pd.date_range(start, end, freq='A')
dr2 = pd.date_range(start, end, freq='AS')
print(len(dr1), dr1)
print(len(dr2), dr2)
输出内容如下
2 DatetimeIndex(['2019-12-31', '2020-12-31'], dtype='datetime64[ns]', freq='A-DEC')
3 DatetimeIndex(['2019-01-01', '2020-01-01', '2021-01-01'], dtype='datetime64[ns]', freq='AS-JAN')
由此可见,由于每年的时间有很多天,所以如果选择不同的天作为分隔点,分出来的数据点的个数是不相同的。
5.2. freq 中的 close
import pandas as pd
import datetime
start = datetime.datetime(2021, 6, 11, 12, 0, 1)
end = datetime.datetime(2021, 6, 11, 13, 0, 1)
dr0 = pd.date_range(start, end, name='dr0', freq='H', closed=None)
dr1 = pd.date_range(start, end, name='dr1', freq='H', closed='left')
dr2 = pd.date_range(start, end, name='dr2', freq='H', closed='right')
print(len(dr0), dr0)
print(len(dr1), dr1)
print(len(dr2), dr2)
输出内容
2 DatetimeIndex(['2021-06-11 12:00:01', '2021-06-11 13:00:01'], dtype='datetime64[ns]', name='dr0', freq='H')
1 DatetimeIndex(['2021-06-11 12:00:01'], dtype='datetime64[ns]', name='dr1', freq='H')
1 DatetimeIndex(['2021-06-11 13:00:01'], dtype='datetime64[ns]', name='dr2', freq='H')
5.3. 系数
时间间隔还可以在freq中使用系数,指定时间段,请看下面的示例。
import pandas as pd
import datetime
start = datetime.datetime(2021, 6, 11, 10, 0, 0)
end = datetime.datetime(2021, 6, 11, 11, 0, 0)
dr1 = pd.date_range(start, end, name='dr1', freq='5min')
dr2 = pd.date_range(start, end, name='dr2', freq='14min')
print(len(dr1), dr1)
print(len(dr2), dr2)
输出结果
13 DatetimeIndex(['2021-06-11 10:00', '2021-06-11 10:05:00',
'2021-06-11 10:10:00', '2021-06-11 10:15:00',
'2021-06-11 10:20:00', '2021-06-11 10:25:00',
'2021-06-11 10:30:00', '2021-06-11 10:35:00',
'2021-06-11 10:40:00', '2021-06-11 10:45:00',
'2021-06-11 10:50:00', '2021-06-11 10:55:00',
'2021-06-11 11:00'],
dtype='datetime64[ns]', name='dr1', freq='5T')
5 DatetimeIndex(['2021-06-11 10:00', '2021-06-11 10:14:00',
'2021-06-11 10:28:00', '2021-06-11 10:42:00',
'2021-06-11 10:56:00'],
dtype='datetime64[ns]', name='dr2', freq='14T')
5.4. 参数列表
年
- A, Y year end frequency
- AS, YS year start frequency
- BAS, BYS business year start frequency
- BA, BY business year end frequency
季度
- Q quarter end frequency
- QS quarter start frequency
- BQ business quarter end frequency
- BQS business quarter start frequency
- 月
- M month end frequency
- MS month start frequency
- BM business month end frequency
- CBMS custom business month start frequency
- BMS business month start frequency
- CBM custom business month end frequency
- SMS semi-month start frequency (1st and 15th)
- SM semi-month end frequency (15th and end of month)
- 周
- W weekly frequency
- 天
- B business day frequency
- D calendar day frequency
- C custom business day frequency
- 小时
- H hourly frequency
- BH business hour frequency
- 分钟
- T, min minutely frequency
- 秒
- S secondly frequency
- 毫秒
- L, ms milliseconds
- 微秒
- U, us microseconds
- 纳秒
- N nanoseconds
6. 参考资料
- pandas 官方, https://www.pypandas.cn/
- pandas API, https://www.pypandas.cn/docs/reference.html
journey
title 分隔方式
section 工作
2021/06/11: 5: Me
2021/06/12: 3: Me
2021/06/13: 1: Me, Cat
section 休息
Go downstairs: 5: Me
Sit down: 5: Me
journey
title 分隔方式
section 工作
2021/06/11: 5: Me
2021/06/12: 3: Me
2021/06/13: 1: Me