Pandas重采样聚合:如何按自定义起始日的跨月周期聚合数据?
自定义跨月周期聚合解决方案
要实现从指定起始日开始的跨月周期聚合,Pandas原生resample的标准频率无法直接满足需求,我们可以通过手动分组+分组聚合的方式实现,步骤如下:
1. 定义周期规则
先明确核心参数:
- 起始基准日:比如
2022-01-13 - 周期跨度:比如每4个月(每个周期覆盖
起始日+N个月-1天的区间)
2. 生成周期边界并给数据分组
先生成覆盖数据时间范围的所有周期区间,再将每条数据映射到对应的周期组:
import pandas as pd import numpy as np # 示例数据(替换为你的实际数据) df = pd.DataFrame( {'val1': [0.01, 0.04, 0.09, -0.02], 'val2': [0.08, -0.07, -0.01, 0.01], 'val3': [0.03, 0.02, 0.01, 0.06]}, index=pd.to_datetime(['2022-01-29', '2022-01-30', '2022-01-31', '2022-02-01']) ) # 配置周期参数 start_date = pd.to_datetime('2022-01-13') period_months = 4 # 每个周期的跨度(月数) # 生成所有周期起始日期(从start_date开始,每period_months生成一个) # 先按月初生成,再调整到13号 cycle_starts = pd.date_range( start=start_date, end=df.index.max() + pd.DateOffset(months=period_months), freq=f'{period_months}MS' ) + pd.DateOffset(days=12) # MS是月初,加12天得到当月13号 # 生成周期结束日期(下一个周期起始日减1天) cycle_ends = cycle_starts[1:] - pd.DateOffset(days=1) # 确保最后一个周期覆盖到数据的最后日期 if cycle_ends[-1] < df.index.max(): cycle_ends = cycle_ends.append(pd.DatetimeIndex([df.index.max()])) # 给每条数据分配所属周期组 start_array = np.array(cycle_starts[:-1]) df['cycle_group'] = np.searchsorted(start_array, df.index, side='right') - 1
3. 执行聚合逻辑
沿用你原有的(df+1).cumprod()-1的聚合逻辑,通过groupby替代resample实现:
# 按周期组计算累积乘积,再取每个周期的最后一个结果 result = ( (df.drop('cycle_group', axis=1) + 1) .groupby(df['cycle_group']) .transform(lambda x: x.cumprod()) - 1 ).groupby(df['cycle_group']).last() # 替换索引为周期结束日期(更直观) result.index = cycle_ends[:len(result)]
关键说明
- 为什么不用
resample?Pandas的resample仅支持标准时间频率(如M/Q)或简单偏移量,无法直接定义「从指定日期开始的跨月周期」,手动分组更灵活可控。 - 如果数据中有早于
start_date的记录,可以根据需求将其归到第一个周期,或者通过df = df[df.index >= start_date]过滤掉。
内容的提问来源于stack exchange,提问作者user1267983
相关产品推荐
相关产品推荐

