重采样方法(resample)
重采样是指将时间序列从一个频率转换到另一个频率的处理过程。如果是将高频率数据聚合到低频率,比如将每日采集的频率变成每月采集,则称为降采样(downsamling);如果将低频率数据转换到高频率数据,比如将每月采集的频率变成每日采集,则称为升采样(upsampling)。
并不是所有的重采样都会划分到降采样与升采样两大类中,比如,将采集数据的频率由每周一转换为每周日,类似于这样的转换既不属于降采样,也不属于升采样。
Pandas中的resample()是一个对常规时间序列数据重新采样和频率转换的便捷的方法,可以对原样本重新处理,其语法格式如下:
resample(rule, how=None, axis=0, fill_method=None, closed=None, label=None,
convention='start', kind=None, loffset=None, limit=None, base=0,
on=None, level=None)
部分参数含义如下:
(1) rule:表示重采样频率的字符串或DateOffset,比如M、5min等。
(2) how:用于产生聚合值的函数名或函数数组,默认为None。
(3) fill_method:表示升采样时如何插值,可以取值为ffill、bfill或None,默认为None。
(4) closed:设置降采样哪一端是闭合的,可取值为right或 left。若设为right,则表示划分为左开右闭的区间;若设为left,则表示划分为左闭右开的区间。
(5) label:表示降采样时设置聚合值的标签。
(6) convention:重采样日期时,低频转高频采用的约定,可以取值为start或end,默认为start。
(7) limit:表示前向或后向填充时,允许填充的最大时期数。
接下来,创建一个时间序列类型的Series对象,示例代码如下。
In [42]: date_index = pd.date_range('2017.7.8', periods=30)
time_ser = pd.Series(np.arange(30), index=date_index)
time_ser
Out[42]:
2017-07-08 0
2017-07-09 1
2017-07-10 2
… 省略N行 …
2017-08-01 24
2017-08-02 25
2017-08-03 26
2017-08-04 27
2017-08-05 28
2017-08-06 29
Freq: D, dtype: int32
上述创建的Series对象是按每天进行采样的,从2017年7月8日开始采集,一共有30天的数据。这时,如果需要改成按每周进行采样,此时可以使用resample()方法重新采样,具体代码如下。
In [43]: time_ser.resample('W-MON', how='mean')
运行上述代码,在单元格下方出现如图1所示的警告信息。
图1 警告信息
图1中的警告表明,how参数不再建议使用,而是采用新的方式“.resample(...).mean()”求平均值。接下来,使用新的方式计算平均值,具体如下。
In [44]: time_ser.resample('W-MON').mean()
Out[44]:
2017-07-10 1.0
2017-07-17 6.0
2017-07-24 13.0
2017-07-31 20.0
2017-08-07 26.5
Freq: W-MON, dtype: float64
从输出结果中可以看出,生成的Series对象中,它的时间戳索引为每周一,数据为每周求得的平均值, 相当于Pandas中的分组操作,只不过是按周进行分组。
如果重新采样时传入closed参数为left,则表示采样的范围是左闭右开型的,也就是说位于此范围的时间序列中,开头的时间戳包含在内,结尾的时间戳是不包含在内的,示例代码如下。
In [45]: time_ser.resample('W-MON', closed='left').mean()
Out[45]:
2017-07-10 0.5
2017-07-17 5.0
2017-07-24 12.0
2017-07-31 19.0
2017-08-07 26.0
Freq: W-MON, dtype: float64
注意:
要进行重采样的对象,必须具有与时间相关的索引,比如DatetimeIndex、PeriodIndex或TimedeltaIndex。