Python大数据分析5:时间采样

时间采样也可以看成是一种时间转换,不同之处在于它往往都采用删除数据或者填充数据的方式来对原始数据本身进行处理。

我们从一个例子开始:

print(frame[‘height’].resample(‘M’).mean())

这个就表示对当前时间进行按照月份为单位的采样,原始的天数信息被粒度更大的月份所替代,这个过程就是一种时间转换。但是单独的使用resample转换没有意义,通常我们的目的是需要对转换后做什么给出说明。比如这里是计算每个月份的身高平均值。

其中,我们还注意到由于粒度变大,因此每月都以当月最后一天来表示。

如果想只显示月份,那么可以通过kind参数来设置:

print(frame[‘height’].resample(‘M’, kind=’period’).mean())

此时period值表示按照月度周期来显示,就是月份信息本身。

细心的同学可能也会想到,这种方法借助于分组不也可以完成吗?当然可以,我们可以将时间索引转换为月份,并分组,显示身高平均值,效果也是一样:

print(frame[‘height’].groupby(frame.index.to_period(freq=’M’)).mean())

但是,采样方法远远不止这个简单,接下来的很多操作就必须利用采样来完成了。

比如我们准备将粒度变小来采样:

print(frame[‘height’].resample(‘H’).mean())

这里的H表示小时,看的出来每天都被强制分隔为24个记录,不过平均身高这个数据只显示一次,多出来的采样记录都为空值。原始时间往往只对应那个最对应的时间点。对于这些空值,显然对于后续的分析可能带来不利的影响,那么这该如何处理呢?

第一种方法最为简单,就是直接利用上级时间粒度对应的数值来填充:

print(frame[‘height’].resample(‘H’).ffill())

这里的ffill方法就实现了所有数值的填充。

可以限定填充的范围,比如只填充到对应时间前后各一个数值,共计2个:

pd.set_option(‘display.max_rows’, None)

print(frame[‘height’].resample(‘H’).ffill(limit=2))

这里需要看到全部记录,因此我们调整了显示全部记录,在中间,我们可以看到对应时间点的前后都被填充个一个数值。

这里面有一个非常关键的问题,就是时间区间的划分问题,大家都学过开区间和闭区间,因此对于这些时间点而言,如何规定它是属于哪一个时间段非常重要。比如我们看第一个记录,时间为2019年11月29日,默认为0点0分0秒。看的出来,默认是采取左闭区间,也就是说,每小时都从0分0秒开始计算,直到59分59秒为止。其实这里59秒并不准确,应该是一分钟中可以表达的带有毫秒等更细信息的最大秒数。

但是有时候,可能也需要表达成右闭区间,比如我们如果认为每小时是从0分1秒开始,其实这里的1秒也不准确,应该是一分钟中可以表达的带有毫秒等更细信息的最小秒数,同时直到下一小时0分0秒为止:

print(frame[‘height’].resample(‘H’, closed=’right’).mean())

此时的close参数表示闭区间,此时以右为准,即右闭区间。我们从结果看的出来。

大家可能没有理解这样的表达有什么实际意义,我们来看一个例子。

dates = [datetime(2019, 11, 29, 1, 2, 0), datetime(2019, 11, 29, 2, 0, 0),

         datetime(2019, 12, 17), datetime(2019, 12, 30), datetime(2020, 1, 1),

         datetime(2020, 1, 3), datetime(2020, 1, 4)]

frame = pd.DataFrame(data, index=dates)

我们把时间做了调整,其中改变了前两条,分别是2019年11月29日1点2分,和同一天的2点整。

现在我们直接按照小时采样:

print(frame[‘height’].resample(‘H’).mean())

可以发现这两个时间位于两个不同的时间段,分别计算各自的身高平均值,很好理解,默认为左闭区间,因此2点整属于一个新的时间段。

但是如果采取了右闭区间,可以看到,两个身高被平均为一个值:

print(frame[‘height’].resample(‘H’, closed=’right’).mean())

显然,在实际时间序列计算中,做出这种区分有时非常必要。

当然这个时候,就存在一个显示的问题,比如第一条记录的结果其实是从1点多开始到2点整为止,那么为何采样时间显示为1点呢?可以不可以也采取右边时间为主的表达方法呢?当然可以,我们再次设定:

print(frame[‘height’].resample(‘H’, label=’right’, closed=’right’).mean())

此时可以看出,第一条记录的时间段显示为右边的2点钟。

最后说明两个例子。

第一个结合简单的例子再次说明下。一般而言常见的时间采样往往发生在年月和季度之间,比如我们将所有的学生的时间都采样为年份:

print(frame[‘height’].resample(‘A’, kind=’period’).mean())

接下来我们使用季度来再次采样并填充:

print(frame.resample(‘Q-DEC’).ffill())

Q-DEC表示季度采样,并以十二月份作为最后一个季度的最后月份。

第二个例子是股票市场中常见的采样操作,即计算各个时间段上的四个值:第一个值(open,开盘)、最大值(high,最高)、最小值(low,最低)、最后一个值(close,收盘),合称为OHLC采样。

按照这个方法,我们对刚才按照年度采样的数据,再次进行了OHLC采样:

print(frame[‘height’].resample(‘A’, kind=’period’).ohlc())

其中,由于2019年有四个身高数值,其中第一个是1.88,也是最高值,最小值为1.78,最后一个值为1.86。大家看懂了吗?

发表评论

邮箱地址不会被公开。 必填项已用*标注