Python pandas生成指定日期范围与时间序列重采样详解
本文详解Python pandas中生成指定日期范围的方法,包括使用date_range设定起止时间、周期及频率。重点讲解时间序列的重采样技术,涵盖通过resample进行降采样(高频转低频)与升采样(低频转高频)的具体操作,解析closed、label等关键参数对聚合结果的影响,并提供基于groupby的替代聚合方案及填充策略。
Python日期的范围、频率、重采样以及频率转换
pandas提供了一套完整的时间序列频率标准,并内置了用于重采样、频率推断以及生成固定频率日期范围的工具集。
生成指定日期范围的方法
pandas.date_range()函数用于生成指定长度的DatetimeIndex对象。
1)默认情况下,date_range会按照时间间隔为天的方式,生成从给定开始时间到结束时间的时间戳数组;
2)如果仅指定开始时间或结束时间,则必须通过periods参数来标定生成的时间长度。
import pandas as pd
pd.date_range('2017-6-20','2017-6-27')
DatetimeIndex(['2017-06-20', '2017-06-21', '2017-06-22', '2017-06-23', '2017-06-24', '2017-06-25', '2017-06-26', '2017-06-27'], dtype='datetime64[ns]', freq='D')
pd.date_range('2017-6-20 12:59:30','2017-6-27')
DatetimeIndex(['2017-06-20 12:59:30', '2017-06-21 12:59:30', '2017-06-22 12:59:30', '2017-06-23 12:59:30', '2017-06-24 12:59:30', '2017-06-25 12:59:30', '2017-06-26 12:59:30'], dtype='datetime64[ns]', freq='D')
pd.date_range('2017-6-20 12:59:30',periods = 8)
DatetimeIndex(['2017-06-20 12:59:30', '2017-06-21 12:59:30', '2017-06-22 12:59:30', '2017-06-23 12:59:30', '2017-06-24 12:59:30', '2017-06-25 12:59:30', '2017-06-26 12:59:30', '2017-06-27 12:59:30'], dtype='datetime64[ns]', freq='D')
pd.date_range('2017-6-20 12:59:30',periods = 8, normalize = True)
DatetimeIndex(['2017-06-20', '2017-06-21', '2017-06-22', '2017-06-23', '2017-06-24', '2017-06-25', '2017-06-26', '2017-06-27'], dtype='datetime64[ns]', freq='D')
频率和日期偏移量
pandas中的频率由一个基础频率(如M、H)或更具体的单位(如Hour、Minute、h、min等)定义。
pd.date_range('2017-6-27',periods = 7,freq = '1h30min')
DatetimeIndex(['2017-06-27 00:00:00', '2017-06-27 01:30:00', '2017-06-27 03:00:00', '2017-06-27 04:30:00', '2017-06-27 06:00:00', '2017-06-27 07:30:00', '2017-06-27 09:00:00'], dtype='datetime64[ns]', freq='90T')
pd.date_range('2017-6-27',periods = 7,freq = 'M')
DatetimeIndex(['2017-06-30', '2017-07-31', '2017-08-31', '2017-09-30', '2017-10-31', '2017-11-30', '2017-12-31'], dtype='datetime64[ns]', freq='M')
pd.date_range('2017-6-27',periods = 7,freq = 'd')
DatetimeIndex(['2017-06-27', '2017-06-28', '2017-06-29', '2017-06-30', '2017-07-01', '2017-07-02', '2017-07-03'], dtype='datetime64[ns]', freq='D')
pd.date_range('2017-6-27',periods = 7,freq = 'H')
DatetimeIndex(['2017-06-27 00:00:00', '2017-06-27 01:00:00', '2017-06-27 02:00:00', '2017-06-27 03:00:00', '2017-06-27 04:00:00', '2017-06-27 05:00:00', '2017-06-27 06:00:00'], dtype='datetime64[ns]', freq='H')
常用的基础频率
| 别名 | 偏移量 | 说明 |
|---|---|---|
| D/d | Day | 每日历日 |
| B | BusinessDay | 每工作日 |
| H/h | Hour | 每小时 |
| T或min | Minute | 每分 |
| S | Secend | 每秒 |
| L或ms | Milli | 每毫秒(每千分之一秒) |
| U | Micro | 每微秒(即百万分之一秒) |
| M | MonthEnd | 每月最后一个日历日 |
| BM | BusinessDayEnd | 每月最后一个工作 |
上表仅展示了部分常用频率。
WOM日期(可获得例如“每月第3个星期五”)
pd.date_range('2017-06-01','2017-07-31',freq='WOM-3FRI')
DatetimeIndex(['2017-06-16', '2017-07-21'], dtype='datetime64[ns]', freq='WOM-3FRI')
重采样及频率转换
降采样:将高频数据转换为低频数据。
升采样:将低频数据转换为高频数据。
主要函数:resample()(pandas对象均具备此方法)。
resample方法的参数说明
| 参数 | 说明 |
|---|---|
| freq | 表示重采样频率,例如‘M'、‘5min',Second(15) |
| how='mean' | 用于产生聚合值的函数名或数组函数,例如‘mean'、‘ohlc'、np.max等,默认是‘mean',其他常用的值由:‘first'、‘last'、‘median'、‘max'、‘min' |
| axis=0 | 默认是纵轴,横轴设置axis=1 |
| fill_method = None | 升采样时如何插值,比如‘ffill'、‘bfill'等 |
| closed = ‘right' | 在降采样时,各时间段的哪一段是闭合的,‘right'或‘left',默认‘right' |
| label= ‘right' | 在降采样时,如何设置聚合值的标签,例如,9:30-9:35会被标记成9:30还是9:35,默认9:35 |
| loffset = None | 面元标签的时间校正值,比如‘-1s'或Second(-1)用于将聚合标签调早1秒 |
| limit=None | 在向前或向后填充时,允许填充的最大时期数 |
| kind = None | 聚合到时期(‘period')或时间戳(‘timestamp'),默认聚合到时间序列的索引类型 |
| convention = None | 当重采样时期时,将低频率转换到高频率所采用的约定(start或end)。默认‘end' |
降采样操作
需考虑以下因素:
1)各区间哪边是闭合的(参数:closed)。
2)如何标记各聚合面元,使用区间的开头还是末尾(参数:label)。
ts_index = pd.date_range('2017-06-20',periods =12,freq = '1min')#一分钟采样数据
ts = pd.Series(np.arange(12),index = ts_index)
ts
2017-06-20 00:00:00 0 2017-06-20 00:01:00 1 2017-06-20 00:02:00 2 2017-06-20 00:03:00 3 2017-06-20 00:04:00 4 2017-06-20 00:05:00 5 2017-06-20 00:06:00 6 2017-06-20 00:07:00 7 2017-06-20 00:08:00 8 2017-06-20 00:09:00 9 2017-06-20 00:10:00 10 2017-06-20 00:11:00 11 Freq: T, dtype: int32
聚合到5分钟
ts.resample('5min',how='sum')
C:\Program Files\anaconda\lib\site-packages\ipykernel\__main__.py:1: FutureWarning: how in .resample() is deprecated the new syntax is .resample(...).sum() if __name__ == '__main__': 2017-06-20 00:00:00 10 2017-06-20 00:05:00 35 2017-06-20 00:10:00 21 Freq: 5T, dtype: int32
ts.resample('5min',how='sum',closed='left')
C:\Program Files\anaconda\lib\site-packages\ipykernel\__main__.py:1: FutureWarning: how in .resample() is deprecated the new syntax is .resample(...).sum() if __name__ == '__main__': 2017-06-20 00:00:00 10 2017-06-20 00:05:00 35 2017-06-20 00:10:00 21 Freq: 5T, dtype: int32
ts.resample('5min',how='sum',closed='left',label ='left')
C:\Program Files\anaconda\lib\site-packages\ipykernel\__main__.py:1: FutureWarning: how in .resample() is deprecated the new syntax is .resample(...).sum() if __name__ == '__main__': 2017-06-20 00:00:00 10 2017-06-20 00:05:00 35 2017-06-20 00:10:00 21 Freq: 5T, dtype: int32
通过groupby进行重插样
另外一种降采样方法
ts1_index = pd.date_range('2017-6-01',periods = 100,freq = 'd')
ts1 = pd.Series(np.arange(100),index = ts1_index)
ts1.head()
2017-06-01 0 2017-06-02 1 2017-06-03 2 2017-06-04 3 2017-06-05 4 Freq: D, dtype: int32
ts1.groupby(lambda x:x.month).mean()
6 14.5 7 45.0 8 76.0 9 95.5 dtype: float64
ts1.groupby(lambda x:x.weekday).mean()
0 49.5 1 50.5 2 51.5 3 49.0 4 50.0 5 47.5 6 48.5 dtype: float64
df1 = pd.DataFrame(np.arange(200).reshape(100,2),index = ts1_index)
df1.groupby(lambda x:x.weekday).mean()
| 0 | 1 | |
|---|---|---|
| 0 | 99 | 100 |
| 1 | 101 | 102 |
| 2 | 103 | 104 |
| 3 | 98 | 99 |
| 4 | 100 | 101 |
| 5 | 95 | 96 |
| 6 | 97 | 98 |
对于具有时间序列索引的pandas数据结构,当groupby传入一个函数时,可以对时间索引对应的列进行聚合。
升采样操作
升采样不涉及聚合,但需要进行数据填充。
df2 = pd.DataFrame(np.arange(200).reshape(100,2),index = ts1_index,columns=['add1','add2']) df2.head()
| add1 | add2 | |
|---|---|---|
| 2017-06-01 | 0 | 1 |
| 2017-06-02 | 2 | 3 |
| 2017-06-03 | 4 | 5 |
| 2017-06-04 | 6 | 7 |
| 2017-06-05 | 8 | 9 |
df2.resample('W-THU',fill_method = 'ffill')
C:\Program Files\anaconda\lib\site-packages\ipykernel\__main__.py:1: FutureWarning: fill_method is deprecated to .resample() the new syntax is .resample(...).ffill() if __name__ == '__main__':
| add1 | add2 | |
|---|---|---|
| 2017-06-01 | 0 | 1 |
| 2017-06-08 | 14 | 15 |
| 2017-06-15 | 28 | 29 |
| 2017-06-22 | 42 | 43 |
| 2017-06-29 | 56 | 57 |
| 2017-07-06 | 70 | 71 |
| 2017-07-13 | 84 | 85 |
| 2017-07-20 | 98 | 99 |
| 2017-07-27 | 112 | 113 |
| 2017-08-03 | 126 | 127 |
| 2017-08-10 | 140 | 141 |
| 2017-08-17 | 154 | 155 |
| 2017-08-24 | 168 | 169 |
| 2017-08-31 | 182 | 183 |
| 2017-09-07 | 196 | 197 |
| 2017-09-14 | 198 | 199 |
总结
本篇博客主要内容:
1)生成指定时间段、指定频率的日期。
2)对含有时间索引的pandas数据进行重采样,包括降采样和升采样等。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









