Pandas按月分组取行时如何保留原始实际最后索引而非月末日历日期
底层原理说明
当你使用时间频率作为分组规则时,pandas的resample和pd.Grouper有明确的默认行为逻辑,几种写法的差异本质是操作类型的不同:
- 使用
freq='1M'分组时,pandas首先会按照日历月的时间区间拆分数据,每个分组的默认标识(分组键)是对应月份的日历最后一天,和原始数据中实际存在的日期无关。 .last()、.agg()属于聚合操作:运算后返回的结果长度和分组数一致,索引会直接使用前面提到的分组键(日历月末日期),因此会覆盖原始的索引值,所以得到的索引不是你需要的实际交易日。.tail(1)属于行筛选操作:直接从每个分组里提取最后1行的完整原始数据,不会修改行的索引标签,因此保留的就是当月实际存在的最后一条数据的原始索引,符合你的需求。
控制resample输出索引的通用方法
resample本身的内置参数仅支持调整基于日历区间的索引规则,不会自动匹配原始数据的实际日期,如果你需要基于resample实现相同效果,有两种通用方案:
- 结合apply和tail直接提取原始行,关闭分组键层级即可
df.resample('1M', group_keys=False).apply(lambda x: x.tail(1))
- 先聚合再手动替换索引为原始数据的当月最大日期
# 先按resample规则取每月最后一行的数值 res = df.resample('1M').last() # 把索引替换为每个月原始数据的实际最大日期 res.index = df.groupby(pd.Grouper(freq='1M')).apply(lambda grp: grp.index.max())
如果你只需要调整resample默认的日历区间索引规则,可以修改以下两个参数:
label:可选left/right,控制索引使用时间区间的左端点还是右端点,比如freq='1M'默认label='right'用月末作为索引,设为left就会用当月1号作为索引closed:可选left/right,控制时间区间的闭合方向,会影响边缘日期的数据被划分到哪个分组
内容的提问来源于stack exchange,提问作者shadowtalker
相关产品推荐
相关产品推荐

