Pandas中resample()重采样与asfreq()频度转换详解

追风的人
追风的人
发布时间:2026-10-13 | 2人浏览过
原创

本文详细介绍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()频度转换的内容即为全部介绍,希望能为读者提供参考,并欢迎大家继续支持本站。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表