文章目录
- 一、生成时间戳范围
-
- 1. 指定值
- 2. 指定开始日期并设置期间数
- 3. 频率 freq
- 4. closed
- 二、Pandas 的时期函数 Period()
- 三、时间序列 - 重采样 resample
- 在开始之前,我们先导入 numpy 和 pandas 库,同时导入 python 内置的模块。
import pandas as pd
import numpy as np
import time
import datetime
一、生成时间戳范围
- 有时候,我们可能想要生成某个范围内的时间戳。例如,我想要生成 “2018-6-26” 这一天之后的 8 天时间戳,我们可以使用
date_range
和 bdate_range
来完成时间戳范围的生成。
- 我们可以通过 date_range() 返回固定频率的 DatetimeIndex。
- 其语法模板如下:
date_range(start=None, end=None, periods=None, freq=None, tz=None, normalize=False, name=None, closed=None, **kwargs)
- 他返回等距时间点的范围(其中任意两个相邻点之间的差值由给定频率指定),以便它们都满足 start <[= ]x <[=] end,其中第一个和最后一个分别为。该范围内的第一个和最后一个时间点位于 freq 的边界(如果以频率字符串的形式给出)或对 freq 有效。
- 其参数含义如下:
- start 表示生成日期的左边界。
- end 表示生成日期的左边界。
- periods 表示要生成的周期数。
- freq 表示频率, default ‘D’ ,频率字符串可以有倍数,例如 ‘5H’。
- tz 表示时区用于返回本地化日期时间索引的时区名称,例如 “Asia/Hong_Kong”。默认情况下,生成的 DatetimeIndex 是时区初始索引。
- normalize: 默认 False, 在生成日期范围之前,将开始/结束日期标准化。
- name:默认 None 设置返回 DatetimeIndex name。
1. 指定值
- 默认是包含开始和结束时间,默认频率使用的 D(天)。
- 示例 1:我们生成从 20210101 到 20210108 之间以天为单位长度的时间戳。
pd.date_range(start='1/1/2021', end='1/08/2021')
- 示例 2:我们生成 2010 年到 2011 年之间以天为单位长度的时间戳。
pd.date_range(start='2010', end='2011')
2. 指定开始日期并设置期间数
pd.date_range(start='1/1/2018', periods=8)
- 我们也可以指定开始、结束和期间,频率就会自动生成(线性间隔)。
- 例如,我们将开始定为 20180424,结束定为 20180427,期间定为 3,那么他就会自动以一天半为间隔进行时间戳的生成。
pd.date_range(start='2018-04-24', end='2018-04-27', periods=3)
- 如果我们不定义开始值,只定义结束值和期间,那么他会向前推导时间戳。
pd.date_range(end='2018-04-24', periods=4)
3. 频率 freq
freq |
描述 |
Y |
年 |
M |
月 |
D |
日(默认) |
T(MIN) |
分钟 |
S |
秒 |
L |
毫秒 |
U |
微妙 |
A-DEC |
每年指定月份的最后一个日历日 |
W-MON |
指定每月的哪个星期开始 |
WOM_2MON |
指定每个月的第几个星期的星期几开始(这里是第二个星期的星期一) |
Q-DEC(Q-月) |
指定月为季度末,每个季度末最后一月的最后一个日历日 |
B,(M,Q,A),S |
分别代表了工作日(以月为频率,以季度为频率,以年为频率),最接近月 |
B |
工作日 |
- 其中,月和星期的缩写基本是英语的前三个字母大写为准。
- 其中,Q-月只有三种情况:1-4-7-10,2-5-8-11,3-6-9-12。
- 例如,我们可以通过 W-MON,从指定星期一开始算起。
pd.date_range('2022/1/1','2022/2/1', freq = 'W-MON')
- 例如,我们可以通过 WOM-2MON,从每月的第二个星期一开始。
pd.date_range('2022/1/1','2022/5/1', freq = 'WOM-2MON')
pd.date_range('2022/1/1','2022/1/5', freq = 'B')
pd.date_range('2022/1/1','2022/1/2', freq = 'H')
pd.date_range('2022/1/1 12:00','2022/1/1 12:10', freq = 'T')
pd.date_range('2022/1/1 12:00:00','2022/1/1 12:00:10', freq = 'S')
pd.date_range('2022/1/1 12:00:00','2022/1/1 12:00:10', freq = 'L')
pd.date_range('2022/1/1 12:00:00','2022/1/1 12:00:10', freq = 'U')
pd.date_range('2017','2018', freq = 'M')
- 我们可以通过 Q-月,返回每个季度末最后一月的最后一个日历日。
print(pd.date_range('2017','2020', freq = 'Q-DEC'))
- 我们可以通过 A-月,返回每年指定月份的最后一个日历日。
print(pd.date_range('2017','2020', freq = 'A-DEC'))
- 我们可以通过 BM 返回每的最后一个工作日,BQ-月返回每个季度末最后一月的最后一个工作日,BA-月返回每年指定月份的最后一个工作日。
pd.date_range('2017','2018', freq = 'BM')
pd.date_range('2017','2020', freq = 'BQ-DEC')
pd.date_range('2017','2020', freq = 'BA-DEC')
- 我们可以通过 pd.date_range() 指定时间频率(下面以 7 天,2 小时 30 分钟,2 月为例)。
print(pd.date_range('2017/1/1','2017/2/1', freq = '7D'))
print(pd.date_range('2017/1/1','2017/1/2', freq = '2h30min'))
print(pd.date_range('2017','2018', freq = '2M'))
4. closed
- closed 是觉得我们是否包含 start 值和 end 值,默认情况下是两个值都包含。
- 如果 closed 设置为 left,则表示不包含 end 值。
- 如果 closed 设置为 right,则表示不包含 start 值。
- 我们先生成初始数据,便于后续的观察。
pd.date_range(start='1/1/2021', end='1/08/2021')
pd.date_range(start='1/1/2021', end='1/08/2021',closed='left')
pd.date_range(start='1/1/2021', end='1/08/2021',closed='right')
- 我们可以通过
bdate_range(start=None, end=None, periods=None, freq='B')
语法返回固定频率的 DatetimeIndex,默认频率为 B(工作日)。
pd.bdate_range(start='2022-01-01', end='2022-02-01')
二、Pandas 的时期函数 Period()
- 我们可以直接使用 period() 输出时期,他默认是 A-DEC(每年指定月份的最后一个日历日)。
p = pd.Period('2017')
p
Period('2017', 'A-DEC')
p = pd.Period('2017-1', freq = 'M')
print(p, type(p))
- (1) 可以通过加减整数可以实现对 Period 的移动(默认是以月为单位进行加减)。
print(p + 1)
print(p - 2)
- (2) 如果两个 Period 对象拥有相同频率,则它们的差就是它们之间的单位数量。
p = pd.Period('2017-1', freq = 'M')
print(p, type(p))
pd.Period('2018', freq='M') - p
- (3) period_range 函数可用于创建规则的时期范围。
rng = pd.period_range('2021-1-1', '2021-6-1')
rng
- (4) PeriodIndex 类的构造函数允许直接使用一组字符串表示一段时期。
- 这里需要注意的是,我们必须指定 freq。
values = ['200103', '200104', '200105']
index = pd.PeriodIndex(values, freq='M')
index
- (5) 时期的频率转换 asfreq。
- freq 当中的 A-月表示每年指定月份的最后一个日历日。
p = pd.Period('2021', freq='A-DEC')
p
- 我们可以使用 asfreq 将时期的频率进行转换 M(月),通过设置 how 的参数为 start 或者 end 决定是起始还是结束。
p.asfreq('M')
- 我们将 how 设置为 start,也可写 how = ‘s’。
p.asfreq('M', how="start")
- 我们将 how 设置为 end,也可写 how = ‘e’。
p.asfreq('M', how="end")
p.asfreq('H',how="s")
- (6) 对于 PeriodIndex 或 TimeSeries 的频率转换方式相同。
- 示例 1:
rng = pd.period_range('2006', '2009', freq='A-DEC')
rng
ts = pd.Series(np.random.rand(len(rng)), rng)
ts
ts.asfreq('M', how='s')
- 示例 5:对 asfreq 的 how 参数不设置就默认为 end。
ts.asfreq('M')
ts2 = pd.Series(np.random.rand(len(rng)), index = rng.asfreq('D', how = 'start'))
ts2
- (7) 时间戳与时期之间的转换:pd.to_period()、pd.to_timestamp()。
- 我们通过生成一个从 20170101 开始,以月为间隔生成 10 个数据和从 2017 到 2018 以月为间隔的两个初始数据,便于后续的操作观察。
rng = pd.date_range('2017/1/1', periods = 10, freq = 'M')
prng = pd.period_range('2017','2018', freq = 'M')
print(rng)
print(prng)
- 通过随机函数生成与 rng 长度个数相同的数据,并将标签设置为 rng。
ts1 = pd.Series(np.random.rand(len(rng)), index = rng)
ts1
- 我们可以将每月最后一日,转化为每月。to_period()参数为空, 推断每日频率(head 表示读取前五个数据)。
ts1.to_period().head()
- 以和 rng 相同的方式通过随机函数生成 prng,并通过 head 读取他的前五个数据。
ts2 = pd.Series(np.random.rand(len(prng)), index = prng)
print(ts2.head())
print(ts2.to_timestamp().head())
三、时间序列 - 重采样 resample
- Pandas 中的 resample 函数,被叫做重新采样,是对原样本重新处理的一个方法,是一个对常规时间序列数据重新采样和频率转换的便捷的方法。
- 他的作用是重新取样时间序列数据。
- 对象必须具有类似 datetime 的索引(DatetimeIndex、PeriodIndex 或 TimedeltaIndex),或将类似 datetime 的值传递给 on 或 level 关键字。
- 其语法模板如下:
DataFrame.resample(rule, closed=None, label=None, level=None)
- 其部分参数含义如下:
- rule 表示目标转换的偏移量字符串或对象。
- closed 表示在降采样时,各时间段的哪一段是闭合的,‘right’ 或 ‘left’,默认‘right’。
- label 表示在降采样时,如何设置聚合值的标签,例如,9:30-9:35会被标记成9:30还是9:35,默认是 9:35。
- 我们可以生成从 20170101 开始的 12 个数,并以他为标签,通过函数生成对应的数据,
rng = pd.date_range('20170101', periods = 12)
ts = pd.Series(np.arange(12), index = rng)
print(ts)
Freq: D, dtype: int32
- 我们将序列下采样到 5 天的数据箱中(以 5 天为时间单位),并将放入数据箱的时间戳的值相加。
ts.resample('5D').sum()
- 我们就会得到一个新的聚合后的 Series,聚合方式为求和,当然,我们也可以生成其他的聚合方式。
print(ts.resample('5D').mean(),'→ 求平均值\n')
print(ts.resample('5D').max(),'→ 求最大值\n')
print(ts.resample('5D').min(),'→ 求最小值\n')
print(ts.resample('5D').median(),'→ 求中值\n')
print(ts.resample('5D').first(),'→ 返回第一个值\n')
print(ts.resample('5D').last(),'→ 返回最后一个值\n')
print(ts.resample('5D').ohlc(),'→ OHLC重采样\n')
- 知识点补充:
- OHLC 是金融领域的时间序列聚合方式,包括 open开盘、high 最大值、low 最小值、close 收盘。
- closed 表示各时间段哪一端是闭合(即包含)的,默认是右端闭合。
- 详解:这里 values 为 0-11,按照 5D 重采样,可以分为以下三类 [1,2,3,4,5],[6,7,8,9,10],[11,12]。
- left 表示指定间隔左边为结束,就是 [1,2,3,4,5],[6,7,8,9,10],[11,12]。
- right 表示指定间隔右边为结束,就是 [1],[2,3,4,5,6],[7,8,9,10,11],[12]。
- 我们将系列降采样到 5 天的箱中,但关闭箱间隔的左侧。
print(ts.resample('5D', closed = 'left').sum(), '→ left\n')
- 我们将系列降采样到 5 天的箱中,但关闭箱间隔的右侧。
print(ts.resample('5D', closed = 'right').sum(), '→ right\n')