python+pandas生成指定日期和重采样的方法

时间:2022-11-22 16:20:45

python 日期的范围、频率、重采样以及频率转换

pandas有一整套的标准时间序列频率以及用于重采样、频率推断、生成固定频率日期范围的工具。

生成指定日期范围的范围

pandas.date_range()用于生成指定长度的DatatimeIndex:

1)默认情况下,date_range会按着时间间隔为天的方式生成从给定开始到结束时间的时间戳数组;

2)如果只指定开始或结束时间,还需要periods标定时间长度。

?
1
2
import pandas as pd
pd.date_range('2017-6-20','2017-6-27')
?
1
2
3
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')
?
1
pd.date_range('2017-6-20 12:59:30','2017-6-27')
?
1
2
3
4
5
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')
?
1
pd.date_range('2017-6-20 12:59:30',periods = 8)
?
1
2
3
4
5
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')
?
1
pd.date_range('2017-6-20 12:59:30',periods = 8, normalize = True)
?
1
2
3
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等)

?
1
pd.date_range('2017-6-27',periods = 7,freq = '1h30min')
?
1
2
3
4
5
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')
?
1
pd.date_range('2017-6-27',periods = 7,freq = 'M')
?
1
2
3
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')
?
1
pd.date_range('2017-6-27',periods = 7,freq = 'd')
?
1
2
3
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')
?
1
pd.date_range('2017-6-27',periods = 7,freq = 'H')
?
1
2
3
4
5
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个星期五”)

?
1
pd.date_range('2017-06-01','2017-07-31',freq='WOM-3FRI')
?
1
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)

?
1
2
ts_index = pd.date_range('2017-06-20',periods =12,freq = '1min')#一分钟采样数据
ts = pd.Series(np.arange(12),index = ts_index)
?
1
 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
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分钟

?
1
ts.resample('5min',how='sum')
?
1
2
3
4
5
6
7
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
?
1
ts.resample('5min',how='sum',closed='left')
?
1
2
3
4
5
6
7
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
?
1
ts.resample('5min',how='sum',closed='left',label ='left')
?
1
2
3
4
5
6
7
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进行重插样

另外一种降采样方法

?
1
2
3
ts1_index = pd.date_range('2017-6-01',periods = 100,freq = 'd')
ts1 = pd.Series(np.arange(100),index = ts1_index)
ts1.head()
?
1
2
3
4
5
6
2017-06-01 0
 2017-06-02 1
 2017-06-03 2
 2017-06-04 3
 2017-06-05 4
 Freq: D, dtype: int32
?
1
ts1.groupby(lambda x:x.month).mean()
?
1
2
3
4
5
6 14.5
7 45.0
8 76.0
9 95.5
dtype: float64
?
1
ts1.groupby(lambda x:x.weekday).mean()
?
1
2
3
4
5
6
7
8
0 49.5
1 50.5
2 51.5
3 49.0
4 50.0
5 47.5
6 48.5
dtype: float64
?
1
df1 = pd.DataFrame(np.arange(200).reshape(100,2),index = ts1_index)
?
1
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传入一个函数时,可以对时间索引对应列进行聚合

升采样

升采样没有聚合,但是需要填充

?
1
2
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

 

?
1
df2.resample('W-THU',fill_method = 'ffill')
?
1
2
3
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数据进行重采样,包括降采样和升采样等。

原文链接:https://blog.csdn.net/LY_ysys629/article/details/73823803