python_时间序列_重采样及频率转换 Resampling and Frequency Conversion¶ # 11.6 重采样及频率转换 # 重采样(resampling)指的是将时间序列从⼀个频率转换到另⼀ # 个频率的处理过程。将⾼频率数据
python_时间序列_重采样及频率转换
Resampling and Frequency Conversion¶# 11.6 重采样及频率转换
# 重采样(resampling)指的是将时间序列从⼀个频率转换到另⼀
# 个频率的处理过程。将⾼频率数据聚合到低频率称为降采样
# (downsampling),⽽将低频率数据转换到⾼频率则称为升采
# 样(upsampling)。并不是所有的重采样都能被划分到这两个⼤
# 类中。例如,将W-WED(每周三)转换为W-FRI既不是降采样
# 461
# 也不是升采样。
# pandas对象都带有⼀个resample⽅法,它是各种频率转换⼯作
# 的主⼒函数。resample有⼀个类似于groupby的API,调⽤
# resample可以分组数据,然后会调⽤⼀个聚合函数:
rng = pd.date_range('2000-01-01', periods=100, freq='D')
ts = pd.Series(np.random.randn(len(rng)), index=rng)
ts
ts.resample('M').mean()
ts.resample('M', kind='period').mean()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-2-617dc4111608> in <module>()
11 # resample可以分组数据,然后会调⽤⼀个聚合函数:
12
---> 13 rng = pd.date_range('2000-01-01', periods=100, freq='D')
14 ts = pd.Series(np.random.randn(len(rng)), index=rng)
15 ts
NameError: name 'pd' is not defined
Downsampling
# 降采样
# 463
# 将数据聚合到规律的低频率是⼀件⾮常普通的时间序列处理任
# 务。待聚合的数据不必拥有固定的频率,期望的频率会⾃动定义
# 聚合的⾯元边界,这些⾯元⽤于将时间序列拆分为多个⽚段。例
# 如,要转换到⽉度频率('M'或'BM'),数据需要被划分到多个单
# ⽉时间段中。各时间段都是半开放的。⼀个数据点只能属于⼀个
# 时间段,所有时间段的并集必须能组成整个时间帧。在⽤
# resample对数据进⾏降采样时,需要考虑两样东⻄:
# 各区间哪边是闭合的。
# 如何标记各个聚合⾯元,⽤区间的开头还是末尾。
import pandas as pd
import numpy as np
rng = pd.date_range('2000-01-01', periods=12, freq='T')
ts = pd.Series(np.arange(12), index=rng)
ts
2000-01-01 00:00:00 0
2000-01-01 00:01:00 1
2000-01-01 00:02:00 2
2000-01-01 00:03:00 3
2000-01-01 00:04:00 4
2000-01-01 00:05:00 5
2000-01-01 00:06:00 6
2000-01-01 00:07:00 7
2000-01-01 00:08:00 8
2000-01-01 00:09:00 9
2000-01-01 00:10:00 10
2000-01-01 00:11:00 11
Freq: T, dtype: int32
假设你想要通过求和的⽅式将这些数据聚合到“5分钟”块中:
# 假设你想要通过求和的⽅式将这些数据聚合到“5分钟”块中:
ts.resample('5min', closed='right').sum()
1999-12-31 23:55:00 0
2000-01-01 00:00:00 15
2000-01-01 00:05:00 40
2000-01-01 00:10:00 11
Freq: 5T, dtype: int32
传⼊的频率将会以“5分钟”的增量定义⾯元边界。默认情况下,⾯
# 元的右边界是包含的,因此00:00到00:05的区间中是包含00:05
# 的。传⼊closed='left'会让区间以左边界闭合:
# 传⼊的频率将会以“5分钟”的增量定义⾯元边界。默认情况下,⾯
# 元的右边界是包含的,因此00:00到00:05的区间中是包含00:05
# 的。传⼊closed='left'会让区间以左边界闭合:
ts.resample('5min', closed='right').sum()
1999-12-31 23:55:00 0
2000-01-01 00:00:00 15
2000-01-01 00:05:00 40
2000-01-01 00:10:00 11
Freq: 5T, dtype: int32
# 最终的时间序列是以各⾯元右边界的时间戳进⾏标记
# 的。传⼊label='right'即可⽤⾯元的邮编界对其进⾏标记:
ts.resample('5min', closed='right', label='right').sum()
2000-01-01 00:00:00 0
2000-01-01 00:05:00 15
2000-01-01 00:10:00 40
2000-01-01 00:15:00 11
Freq: 5T, dtype: int32
最后,你可能希望对结果索引做⼀些位移,⽐如从右边界减去⼀
# 秒以便更容易明⽩该时间戳到底表示的是哪个区间。只需通过
# loffset设置⼀个字符串或⽇期偏移量即可实现这个⽬的:
# 最后,你可能希望对结果索引做⼀些位移,⽐如从右边界减去⼀
# 秒以便更容易明⽩该时间戳到底表示的是哪个区间。只需通过
# loffset设置⼀个字符串或⽇期偏移量即可实现这个⽬的:
ts.resample('5min', closed='right',
label='right', loffset='-1s').sum()
1999-12-31 23:59:59 0
2000-01-01 00:04:59 15
2000-01-01 00:09:59 40
2000-01-01 00:14:59 11
Freq: 5T, dtype: int32
Open-High-Low-Close (OHLC) resampling
OHLC重采样
# ⾦融领域中有⼀种⽆所不在的时间序列聚合⽅式,即计算各⾯元
# 的四个值:第⼀个值(open,开盘)、最后⼀个值(close,收
# 盘)、最⼤值(high,最⾼)以及最⼩值(low,最低)。传⼊
# how='ohlc'即可得到⼀个含有这四种聚合值的DataFrame。整个
# 过程很⾼效,只需⼀次扫描即可计算出结果:
# OHLC重采样
# ⾦融领域中有⼀种⽆所不在的时间序列聚合⽅式,即计算各⾯元
# 的四个值:第⼀个值(open,开盘)、最后⼀个值(close,收
# 盘)、最⼤值(high,最⾼)以及最⼩值(low,最低)。传⼊
# how='ohlc'即可得到⼀个含有这四种聚合值的DataFrame。整个
# 过程很⾼效,只需⼀次扫描即可计算出结果:
ts.resample('5min').ohlc()
open high low close
2000-01-01 00:00:00 0 4 0 4
2000-01-01 00:05:00 5 9 5 9
2000-01-01 00:10:00 10 11 10 11
Upsampling and Interpolation
升采样和插值
# 在将数据从低频率转换到⾼频率时,就不需要聚合了。我们来看
# ⼀个带有⼀些周型数据的DataFrame:
# 升采样和插值
# 在将数据从低频率转换到⾼频率时,就不需要聚合了。我们来看
# ⼀个带有⼀些周型数据的DataFrame:
frame = pd.DataFrame(np.random.randn(2, 4),
index=pd.date_range('1/1/2000', periods=2,
freq='W-WED'),
columns=['Colorado', 'Texas', 'New York', 'Ohio'])
frame
Colorado Texas New York Ohio
2000-01-05 -0.149378 -0.509131 -1.183238 0.278487
2000-01-12 -0.600444 3.604595 1.125173 -1.316800
当你对这个数据进⾏聚合,每组只有⼀个值,这样就会引⼊缺失
# 值。我们使⽤asfreq⽅法转换成⾼频,不经过聚合:
# 当你对这个数据进⾏聚合,每组只有⼀个值,这样就会引⼊缺失
# 值。我们使⽤asfreq⽅法转换成⾼频,不经过聚合:
df_daily = frame.resample('D').asfreq()
df_daily
Colorado Texas New York Ohio
2000-01-05 -0.149378 -0.509131 -1.183238 0.278487
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.600444 3.604595 1.125173 -1.316800
假设你想要⽤前⾯的周型值填充“⾮星期三”。resampling的填充
# 和插值⽅式跟fillna和reindex的⼀样:
# 假设你想要⽤前⾯的周型值填充“⾮星期三”。resampling的填充
# 和插值⽅式跟fillna和reindex的⼀样:
frame.resample('D').ffill()
Colorado Texas New York Ohio
2000-01-05 -0.149378 -0.509131 -1.183238 0.278487
2000-01-06 -0.149378 -0.509131 -1.183238 0.278487
2000-01-07 -0.149378 -0.509131 -1.183238 0.278487
2000-01-08 -0.149378 -0.509131 -1.183238 0.278487
2000-01-09 -0.149378 -0.509131 -1.183238 0.278487
2000-01-10 -0.149378 -0.509131 -1.183238 0.278487
2000-01-11 -0.149378 -0.509131 -1.183238 0.278487
2000-01-12 -0.600444 3.604595 1.125173 -1.316800
这⾥也可以只填充指定的时期数(⽬的是限制前⾯的观测
# 值的持续使⽤距离):
# 这⾥也可以只填充指定的时期数(⽬的是限制前⾯的观测
# 值的持续使⽤距离):
frame.resample('D').ffill(limit=2)
Colorado Texas New York Ohio
2000-01-05 -0.149378 -0.509131 -1.183238 0.278487
2000-01-06 -0.149378 -0.509131 -1.183238 0.278487
2000-01-07 -0.149378 -0.509131 -1.183238 0.278487
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.600444 3.604595 1.125173 -1.316800
注意,新的⽇期索引完全没必要跟旧的重叠:
# 注意,新的⽇期索引完全没必要跟旧的重叠:
frame.resample('W-THU').ffill()
Colorado Texas New York Ohio
2000-01-06 -0.149378 -0.509131 -1.183238 0.278487
2000-01-13 -0.600444 3.604595 1.125173 -1.316800
Resampling with Periods
通过时期进⾏重采样
# 对那些使⽤时期索引的数据进⾏重采样与时间戳很像:
# 通过时期进⾏重采样
# 对那些使⽤时期索引的数据进⾏重采样与时间戳很像:
frame = pd.DataFrame(np.random.randn(24, 4),
index=pd.period_range('1-2000', '12-2001',
freq='M'),
columns=['Colorado', 'Texas', 'New York', 'Ohio'])
frame[:5]
annual_frame = frame.resample('A-DEC').mean()
annual_frame
Colorado Texas New York Ohio
2000 -0.125607 0.239264 0.159813 -0.175475
2001 -0.053293 -0.190562 -0.136178 -0.115108
升采样要稍微麻烦⼀些,因为你必须决定在新频率中各区间的哪
# 端⽤于放置原来的值,就像asfreq⽅法那样。convention参数默
# 认为'end',可设置为'start':
# 升采样要稍微麻烦⼀些,因为你必须决定在新频率中各区间的哪
# 端⽤于放置原来的值,就像asfreq⽅法那样。convention参数默
# 认为'end',可设置为'start':
# Q-DEC: Quarterly, year ending in December
annual_frame.resample('Q-DEC').ffill()
annual_frame.resample('Q-DEC', convention='end').ffill()
Colorado Texas New York Ohio
2000Q4 -0.125607 0.239264 0.159813 -0.175475
2001Q1 -0.125607 0.239264 0.159813 -0.175475
2001Q2 -0.125607 0.239264 0.159813 -0.175475
2001Q3 -0.125607 0.239264 0.159813 -0.175475
2001Q4 -0.053293 -0.190562 -0.136178 -0.115108
由于时期指的是时间区间,所以升采样和降采样的规则就⽐较严
# 格:
# 在降采样中,⽬标频率必须是源频率的⼦时期
# (subperiod)。
# 在升采样中,⽬标频率必须是源频率的超时期
# (superperiod)。
# 如果不满⾜这些条件,就会引发异常。这主要影响的是按季、
# 年、周计算的频率。例如,由Q-MAR定义的时间区间只能升采
# 样为A-MAR、A-JUN、A-SEP、A-DEC等:
# 由于时期指的是时间区间,所以升采样和降采样的规则就⽐较严
# 格:
# 在降采样中,⽬标频率必须是源频率的⼦时期
# (subperiod)。
# 在升采样中,⽬标频率必须是源频率的超时期
# (superperiod)。
# 如果不满⾜这些条件,就会引发异常。这主要影响的是按季、
# 年、周计算的频率。例如,由Q-MAR定义的时间区间只能升采
# 样为A-MAR、A-JUN、A-SEP、A-DEC等:
annual_frame.resample('Q-MAR').ffill()
Colorado Texas New York Ohio
2000Q4 -0.125607 0.239264 0.159813 -0.175475
2001Q1 -0.125607 0.239264 0.159813 -0.175475
2001Q2 -0.125607 0.239264 0.159813 -0.175475
2001Q3 -0.125607 0.239264 0.159813 -0.175475
2001Q4 -0.053293 -0.190562 -0.136178 -0.115108
2002Q1 -0.053293 -0.190562 -0.136178 -0.115108
2002Q2 -0.053293 -0.190562 -0.136178 -0.115108
2002Q3 -0.053293 -0.190562 -0.136178 -0.115108