上篇文章中,我们学习了如何使用pandas库中的date_range()函数生成时间序列索引,而且我们知道我们可以生成不同频率的时间索引,比如按小时、按天、按周、按月等等,因此就会引出另外一个问题,如果我们相对数据做不同频率的转换,该怎么做,pandas库中是否有现成的方法可供使用呢?带着这个问题,我们本次就来学习下数据重采样的知识。
首先,简单解释什么是数据重采样,所谓数据重采样就是将数据原有的频率转换到另一个频率上,如果是从低频率转换到高频率,那么就是升采样,比如原来的数据是按月统计的,通过升采样可以转换为按日的序列数据;相反,如果原来的数据是按日的时间序列数据,通过转换函数转换为按月的时间序列数据,那么我们就将这个过程称为降采样。不管是升采样还是降采样,都通过pandas中的resample函数完成,下面我们就具体来学习这个函数。
pandas.DataFrame.resample
pandas.DataFrame.resample()这个函数主要是用来对时间序列做频率转换,函数原型如下:
DataFrame.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),各参数含义如下列表:
重采样参数含义
降采样(高频数据到低频数据)
上面我们已经知道了重采样的函数和函数各参数的含义,下面我们就用一个例子演示降采样的过程。为了方便观察,这里我们生成10条日数据,如下:
import pandas as pdimport numpy as npindex=pd.date_range('20190115','20190125',freq='D')data1=pd.Series(np.arange(len(index)),index=index)
10条日数据
如上图,这里有10条日数据,现在我们将这按日统计的数据通过降采样的方法转化为按3日求和统计的数据,如下:
data1.resample(rule='3D',how='sum')
降采样
可以看到,原来10条按日统计的数据经过降采样转换变为4条(最后一条是2日的数据和)按每3天统计的数据,这就是降采样的过程,这里需要注意的是起算的节点。上面的例子中label这个参数默认的是left,现在我们改为right,看看有什么区别,如下:
data1.resample(rule='3D',how='sum',label='right')
label=left vs label=right
通过上面的对比,可以得出label这个参数控制了分组后聚合标签的取值。在label为right的情况下,将取分箱右侧的值作为新的标签。上面这个例子基本上演示了降采样的过程,当然我们可以调整how这个参数值进行不同的取值,如下:
data1.resample(rule='3D',how='mean')#取3天的平均值
how=mean
也可以将聚合方法写到外面,如下:
data1.resample(rule='3D').mean()
取3天的平均值
取3天的最小值作为新标签值:
取3天的最小值
升采样(低频数据到高频数据)
上面演示了降采样的过程,下面我们演示升采样的过程,根据升采样的定义,我们只需在resample函数中改变频率即可,但与降采样不同的是升采样后新增频率的数为空值,为此,rasample也提供了3种方式进行填充,下面我们通过代码来演示。
data1.resample(rule='6H').asfreq()
按6小时进行升采样
可以看到,将原来的按日的数据进行升采样为6小时时,会产生很多空值,对于这种空值resample提供了3种方式,分别为ffill(取前面的值)、bfill(取后面的值)、interpolate(线性取值),这里我们分别进行测试,如下:
data1.resample(rule='6H').ffill()
按前面的值进行填充
可以看到,在ffill不带任何数字的情况下,填充了所有的空值,这里我们可以输入个数,从而指定要填充的空值个数,如下:
data1.resample(rule='6H').ffill(2)
填充2个
data1.resample(rule='6H').bfill()
用后面的值填充
data1.resample(rule='6H').interpolate()
线性填充