本系列文章配套代码获取有以下三种途径:
-
可以在以下网站查看,该网站是使用JupyterLite搭建的web端Jupyter环境,因此无需在本地安装运行环境即可使用,首次运行浏览器需要下载一些配置文件(大约20M):
https://returu.github.io/Python_Data_Analysis/lab/index.html
-
也可以通过百度网盘获取,需要在本地配置代码运行环境,环境配置可以查看【Python基础】2.搭建Python开发环境:
链接:https://pan.baidu.com/s/1MYkeYeVAIRqbxezQECHwcA?pwd=mnsj
提取码:mnsj
-
前往GitHub详情页面,单击 code 按钮,选择Download ZIP选项:
https://github.com/returu/Python_Data_Analysis
根据《Python for Data Analysis 3rd Edition》翻译整理
—————————————————–
重新采样(Resampling)是指将时间序列从一个频率转换为另一个频率的过程。
将较高频率数据聚合到较低频率称为向下采样,而将较低频率转换为较高频率称为向上采样。
并非所有重新采样都属于这两个类别中的任何一个。例如,将 W-WED(每周三)转换为 W-FRI(每周五) 既不是向上采样也不是向下采样。
pandas 对象具有 resample 方法,这是所有频率转换的工具函数。resample 具有与 groupby 类似的 API:调用 resample 对数据进行分组,然后再调用聚合函数:
1>>> dates = pd.date_range("2022-01-01", periods=100)
2
3>>> ts = pd.Series(np.arange(len(dates)), index=dates)
4>>> ts
52022-01-01 0
62022-01-02 1
72022-01-03 2
82022-01-04 3
92022-01-05 4
10 ..
112022-04-06 95
122022-04-07 96
132022-04-08 97
142022-04-09 98
152022-04-10 99
16Freq: D, Length: 100, dtype: int32
17
18>>> ts.resample("M").max()
192022-01-31 30
202022-02-28 58
212022-03-31 89
222022-04-30 99
23Freq: M, dtype: int32
24
25>>> ts.resample(rule="M",kind="period").max() #对区间进行聚合262022-01 30
272022-02 58
282022-03 89
292022-04 99
30Freq: M, dtype: int32
resample 是一种灵活且高性能的方法,可用于处理大型时间序列。下表总结了resample的一些选项。
参数 |
说明 |
rule | 表示所需重采样频率的字符串、DateOffset或timedelta对象(例如,’M’、’5min’或Second(15)) |
axis | 需要重新采样的轴;默认情况axis=0 |
fill_method | 向上采样时的插值方式,"ffill" 或 "bfill" ; 默认不进行插值 |
closed | 向下采样时每个区间的哪一端是封闭的(包含的),"right" 或 "left" |
label | 向下采样时,如何使用"right" 或 "left" 的箱体标签标记聚合结果(例如,9:30到9:35的5分钟间隔可以被标记为9:30或9:35) |
limit | 当向前或向后填充时,填充区间的最大值 |
kind | 对区间("period" )或时间戳("timestamp" )的聚合;默认为时间序列索引的类型 |
convention | 在对区间重新采样时,用于将低频率转换为高频率的约定("start" 或 "end" ) ;默认为“end” |
origin | 确定重采样箱边缘的“基础”时间戳;也可以是"epoch" , "start" , "start_day" , "end" , 或"end_day" 之一 |
offset | 添加到原始数据上的偏移时间间隔; 默认为None |
向下采样将数据聚合到一个规则的、较低的频率。你正在聚合的数据不必是固定频率的,所需要的频率定义类用于对时间序列切片以聚合的箱体(bins)边缘。
例如,要将时间转换为每月(M或BM),需要将数据分成一个月的时间间隔。每个间隔是半闭合的,一个数据点只属于一个时间间隔,时间间隔的并集必须是整个时间范围。
-
每段时间间隔的哪一边是闭合的;
-
如何在时间间隔的起始或结束位置标记每个已聚合的箱体bins。
1# 首先生成一些一小时内的频率数据
2>>> dates = pd.date_range("2022-01-01", periods=12, freq="H")
3
4>>> ts = pd.Series(np.arange(len(dates)), index=dates)
5>>> ts
62022-01-01 00:00:00 0
72022-01-01 01:00:00 1
82022-01-01 02:00:00 2
92022-01-01 03:00:00 3
102022-01-01 04:00:00 4
112022-01-01 05:00:00 5
122022-01-01 06:00:00 6
132022-01-01 07:00:00 7
142022-01-01 08:00:00 8
152022-01-01 09:00:00 9
162022-01-01 10:00:00 10
172022-01-01 11:00:00 11
18Freq: H, dtype: int32
19
20# 通过计算每一组的加和将这些数据聚合到5小时的块或柱内
21>>> ts.resample("5h").sum()
222022-01-01 00:00:00 10
232022-01-01 05:00:00 35
242022-01-01 10:00:00 21
25Freq: 5H, dtype: int32
-
closed参数:
1# closed="left":向下采样时每个区间的左端是封闭的(包含的)
2# 此时,传递的频率以5小时的增量定义箱体边界。对于这个频率,默认情况下,左箱体边界是包含的,
3# 因此00:00值包含在00:00 到05:00 时间间隔内,而05:00值不包含在该时间间隔内。
4>>> ts.resample("5h" , closed="left").sum()
52022-01-01 00:00:00 10
62022-01-01 05:00:00 35
72022-01-01 10:00:00 21
8Freq: 5H, dtype: int32
9
10# closed="right":向下采样时每个区间的右端是封闭的(包含的)
11# 因此00:00值不包含在00:00 到05:00 时间间隔内,而05:00值包含在该时间间隔内。
12>>> ts.resample("5h" , closed="right").sum()
132021-12-31 19:00:00 0
142022-01-01 00:00:00 15
152022-01-01 05:00:00 40
162022-01-01 10:00:00 11
17Freq: 5H, dtype: int32
-
label参数:
1# 生成的时间序列由每个箱体左侧的时间戳标记。通过传递 label="right",你可以用右箱体边界标记它们
2>>> ts.resample("5h" , closed="right" , label="right").sum()
32022-01-01 00:00:00 0
42022-01-01 05:00:00 15
52022-01-01 10:00:00 40
62022-01-01 15:00:00 11
7Freq: 5H, dtype: int32
-
to_offset:
如果希望将结果索引移动一定的数量。例如从右边界减去一小时,以便更清楚时间戳指的是那个时间间隔。要实现该功能,需要向结果索引添加一个偏移量。
1>>> from pandas.tseries.frequencies import to_offset
2
3>>> result = ts.resample("5h", closed="right", label="right").sum()
4>>> result
52022-01-01 00:00:00 0
62022-01-01 05:00:00 15
72022-01-01 10:00:00 40
82022-01-01 15:00:00 11
9Freq: 5H, dtype: int32
10
11>>> result.index = result.index + to_offset("-1h")
12
13>>> result
142021-12-31 23:00:00 0
152022-01-01 04:00:00 15
162022-01-01 09:00:00 40
172022-01-01 14:00:00 11
18Freq: 5H, dtype: int32
在金融领域,聚合时间序列的一种流行方法是为每个桶计算四个值:第一个值(开端)、最后一个值(结束)、最大值(峰值)、最小值(谷值)。
通过使用 ohlc 聚合函数,将会获得包含四种聚合值的DataFrame,这些值在数据的单词函数调用中被高效计算:
1>>> ts = pd.Series(np.random.permutation(np.arange(len(dates))), index=dates)
2>>> ts
32022-01-01 00:00:00 11
42022-01-01 01:00:00 7
52022-01-01 02:00:00 4
62022-01-01 03:00:00 10
72022-01-01 04:00:00 1
82022-01-01 05:00:00 8
92022-01-01 06:00:00 5
102022-01-01 07:00:00 2
112022-01-01 08:00:00 6
122022-01-01 09:00:00 3
132022-01-01 10:00:00 0
142022-01-01 11:00:00 9
15Freq: H, dtype: int32
16
17>>> ts.resample("5h").ohlc()
18 open high low close
192022-01-01 00:00:00 11 11 1 1
202022-01-01 05:00:00 8 8 2 3
212022-01-01 10:00:00 0 9 0 9
向上采样是从较低频率转换为较高频率,不需要聚合。
1# 首先生成一个包含每周数据的DataFrame
2>>> df = pd.DataFrame(np.arange(6).reshape((2, 3)),
3... index=pd.date_range("2022-01-01",periods=2,freq="W-MON"),# W-MON:每周一
4... columns=["A", "B", "C"])
5
6>>> df
7 A B C
82022-01-03 0 1 2
92022-01-10 3 4 5
当对该数据使用聚合函数时,每一组只有一个值,会在间隙中产生缺失值。使用 asfreq 方法在不聚合的情况下转换到更高频率:
1>>> df_daily = df.resample("D").asfreq()
2>>> df_daily
3 A B C
42022-01-03 0.0 1.0 2.0
52022-01-04 NaN NaN NaN
62022-01-05 NaN NaN NaN
72022-01-06 NaN NaN NaN
82022-01-07 NaN NaN NaN
92022-01-08 NaN NaN NaN
102022-01-09 NaN NaN NaN
112022-01-10 3.0 4.0 5.0
fillna和reindex方法中可用的填充或插值方法可用于重采样。
1# 假设你想在非周一的日期上向前填充每周数值
2>>> df.resample("D").ffill()
3 A B C
42022-01-03 0 1 2
52022-01-04 0 1 2
62022-01-05 0 1 2
72022-01-06 0 1 2
82022-01-07 0 1 2
92022-01-08 0 1 2
102022-01-09 0 1 2
112022-01-10 3 4 5
12
13# 也可以选择仅向前填充一定数量的区间,以限制继续使用观测值的时距离
14>>> df.resample("D").ffill(limit=3)
15 A B C
162022-01-03 0.0 1.0 2.0
172022-01-04 0.0 1.0 2.0
182022-01-05 0.0 1.0 2.0
192022-01-06 0.0 1.0 2.0
202022-01-07 NaN NaN NaN
212022-01-08 NaN NaN NaN
222022-01-09 NaN NaN NaN
232022-01-10 3.0 4.0 5.0
需要注意的是,新日期索引根本不需要与旧日期索引重合:
1# W-TUE:每周二
2>>> df.resample("W-TUE").ffill()
3 A B C
42022-01-04 0 1 2
52022-01-11 3 4 5
本篇文章来源于微信公众号: 码农设计师