Pandas中resample()重采样与asfreq()频度转换详解
本文详细介绍Pandas中时间序列处理的两种核心方法:resample()重采样与asfreq()频度转换。重点解析降采样时的closed与label参数对区间闭合及标签的影响,以及升采样时利用ffill和bfill进行缺失值填充的策略,并对比asfreq不进行聚合仅转换频率的特性,附带分组重采样示例。
Pandas重采样与频度转换概述
resample()
resample()函数用于执行重采样操作。
重采样(Resampling)是指将时间序列数据的频率转换为另一种频率的过程。具体而言,将高频数据转换为低频数据称为降采样(downsampling),而将低频数据转换为高频数据则称为增采样(upsampling)。
降采样参数详解
降采样
在进行降采样时,需考虑以下关键因素:
确定各时间区间的闭合方向(通过参数closed控制)。
确定如何标记各聚合后的时间片,即使用区间的起始时间还是结束时间作为标签(通过参数label控制)。
In [232]: ts_index = pd.date_range('2018-08-03',periods =12,freq = 'T')
In [233]: ts = pd.Series(np.arange(12),index = ts_index)
In [234]: ts
Out[234]:
2018-08-03 00:00:00 0
2018-08-03 00:01:00 1
2018-08-03 00:02:00 2
2018-08-03 00:03:00 3
2018-08-03 00:04:00 4
2018-08-03 00:05:00 5
2018-08-03 00:06:00 6
2018-08-03 00:07:00 7
2018-08-03 00:08:00 8
2018-08-03 00:09:00 9
2018-08-03 00:10:00 10
2018-08-03 00:11:00 11
Freq: T, dtype: int32
默认情况下,Pandas使用左标签(label='left')且区间为左闭合(closed='left')。
在此默认设置下,第一个时间区间为2018-08-03 00:00:00至2018-08-03 00:04:59,该区间内的数据求和(sum)结果为10,对应的标签显示为2018-08-03 00:00:00。
In [235]: ts.resample('5min').sum()
Out[235]:
2018-08-03 00:00:00 10
2018-08-03 00:05:00 35
2018-08-03 00:10:00 21
Freq: 5T, dtype: int32
若指定区间为右闭合(closed='right'),但保持默认使用左标签(label='left')。
此时第一个时间区间变为2018-08-02 23:55:01至2018-08-03 00:00:00,该区间内无数据,故求和(sum)结果为0,标签显示为2018-08-02 23:55:00。
In [236]: ts.resample('5min',closed='right').sum()
Out[236]:
2018-08-02 23:55:00 0
2018-08-03 00:00:00 15
2018-08-03 00:05:00 40
2018-08-03 00:10:00 11
Freq: 5T, dtype: int32
若同时指定区间为右闭合(closed='right')且使用右标签(label='right')。
此时第一个时间区间仍为2018-08-02 23:55:01至2018-08-03 00:00:00,求和(sum)结果为0,但标签显示为2018-08-03 00:00:00。
In [237]: ts.resample('5min',closed='right',label='right').sum()
Out[237]:
2018-08-03 00:00:00 0
2018-08-03 00:05:00 15
2018-08-03 00:10:00 40
2018-08-03 00:15:00 11
Freq: 5T, dtype: int32
升采样与缺失值处理
升采样
在进行升采样时,主要考虑因素包括:
由于没有聚合操作,但数据频率增加导致出现空值,因此需要进行填充处理。
In [244]: frame = pd.DataFrame(np.random.randn(2, 4),
...: index=pd.date_range('1/1/2000', periods=2,
...: freq='W-WED'), # freq='W-WED'表示按周
...: columns=['Colorado', 'Texas', 'New York', 'Ohio'])
In [245]: frame
Out[245]:
Colorado Texas New York Ohio
2000-01-05 1.201713 0.029819 -1.366082 -1.325252
2000-01-12 -0.711291 -1.070133 1.469272 0.809806
当对数据进行聚合时,每个组仅包含一个原始值,且间隔(gap)之间存在缺失值。若不使用任何聚合函数,
我们可以使用asfreq方法将数据转换为更高的频率。
In [246]: df_daily = frame.resample('D').asfreq()
In [247]: df_daily
Out[247]:
Colorado Texas New York Ohio
2000-01-05 1.201713 0.029819 -1.366082 -1.325252
2000-01-06 NaN NaN NaN NaN
2000-01-07 NaN NaN NaN NaN
2000-01-08 NaN NaN NaN NaN
2000-01-09 NaN NaN NaN NaN
2000-01-10 NaN NaN NaN NaN
2000-01-11 NaN NaN NaN NaN
2000-01-12 -0.711291 -1.070133 1.469272 0.809806
可以使用ffill()方法进行前向填充。
In [248]: frame.resample('D').ffill()
Out[248]:
Colorado Texas New York Ohio
2000-01-05 1.201713 0.029819 -1.366082 -1.325252
2000-01-06 1.201713 0.029819 -1.366082 -1.325252
2000-01-07 1.201713 0.029819 -1.366082 -1.325252
2000-01-08 1.201713 0.029819 -1.366082 -1.325252
2000-01-09 1.201713 0.029819 -1.366082 -1.325252
2000-01-10 1.201713 0.029819 -1.366082 -1.325252
2000-01-11 1.201713 0.029819 -1.366082 -1.325252
2000-01-12 -0.711291 -1.070133 1.469272 0.809806
In [249]: frame.resample('D').ffill(limit=2)
Out[249]:
Colorado Texas New York Ohio
2000-01-05 1.201713 0.029819 -1.366082 -1.325252
2000-01-06 1.201713 0.029819 -1.366082 -1.325252
2000-01-07 1.201713 0.029819 -1.366082 -1.325252
2000-01-08 NaN NaN NaN NaN
2000-01-09 NaN NaN NaN NaN
2000-01-10 NaN NaN NaN NaN
2000-01-11 NaN NaN NaN NaN
2000-01-12 -0.711291 -1.070133 1.469272 0.809806
新生成的日期索引无需与原始数据的时间点完全重叠。
In [250]: frame.resample('W-THU').ffill()
Out[250]:
Colorado Texas New York Ohio
2000-01-06 1.201713 0.029819 -1.366082 -1.325252
2000-01-13 -0.711291 -1.070133 1.469272 0.809806
分组重采样示例
分组重采样
In [279]: times = pd.date_range('2018-08-3 00:00', freq='1min', periods=10)
In [280]: df2 = pd.DataFrame({'time': times.repeat(3),
...: 'key': np.tile(['a', 'b', 'c'], 10),
...: 'value': np.arange(30)})
In [281]: df2[:5]
Out[281]:
key time value
0 a 2018-08-03 00:00:00 0
1 b 2018-08-03 00:00:00 1
2 c 2018-08-03 00:00:00 2
3 a 2018-08-03 00:01:00 3
4 b 2018-08-03 00:01:00 4
In [282]: df2.groupby(['key',pd.Grouper(key='time',freq='5min')]).sum()
Out[282]:
value
key time
a 2018-08-03 00:00:00 30
2018-08-03 00:05:00 105
b 2018-08-03 00:00:00 35
2018-08-03 00:05:00 110
c 2018-08-03 00:00:00 40
2018-08-03 00:05:00 115
asfreq频度转换方法
asfreq()
asfreq()函数用于执行频率转换。
>>> index = pd.date_range('1/1/2000', periods=4, freq='T')
>>> series = pd.Series([0.0, None, 2.0, 3.0], index=index)
>>> df = pd.DataFrame({'s':series})
>>> df
s
2000-01-01 00:00:00 0.0
2000-01-01 00:01:00 NaN
2000-01-01 00:02:00 2.0
2000-01-01 00:03:00 3.0
将数据频率转换为30秒。
>>> df.asfreq(freq='30S')
s
2000-01-01 00:00:00 0.0
2000-01-01 00:00:30 NaN
2000-01-01 00:01:00 NaN
2000-01-01 00:01:30 NaN
2000-01-01 00:02:00 2.0
2000-01-01 00:02:30 NaN
2000-01-01 00:03:00 3.0
将数据频率转换为2分钟,此操作不会执行重采样聚合(这是与resample()的主要区别)。
>>> df.asfreq(freq='2min')
s
2000-01-01 00:00:00 0.0
2000-01-01 00:02:00 2.0
可以使用bfill()方法进行后向填充。
>>> df.asfreq(freq='30S').bfill()
s
2000-01-01 00:00:00 0.0
2000-01-01 00:00:30 NaN
2000-01-01 00:01:00 NaN
2000-01-01 00:01:30 2.0
2000-01-01 00:02:00 2.0
2000-01-01 00:02:30 3.0
2000-01-01 00:03:00 3.0
以上关于Pandas中resample()重采样和asfreq()频度转换的内容即为全部介绍,希望能为读者提供参考,并欢迎大家继续支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









