You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在反转的MultiIndex层级上应用pandas反向expanding窗口计算?

在MultiIndex DataFrame上实现反向Expanding计算

没问题,我来帮你搞定这个需求!要对每个Level-0索引(比如'A'、'B'、'C')执行反向expanding计算(也就是从当前行往最后一行累积,而非从第一行开始),核心思路是先反转组内的时间序列,执行普通的expanding操作后再反转回来。下面结合你的示例数据一步步实现:

步骤说明与代码实现

首先回顾你的示例数据生成代码(方便上下文理解):

import numpy as np
import pandas as pd

np.random.seed(456)
j = [(a, b) for a in ['A','B','C'] for b in pd.date_range('2018-01-01', periods=5, freq='W')]
i = pd.MultiIndex.from_tuples(j, names=['Name','Num'])
df = pd.DataFrame(np.random.randn(15), i, columns=['Vals'])
df.loc[df['Vals'] < 0] = np.nan

方法1:通用反向Expanding(支持任意聚合函数)

这个方法适用于所有expanding支持的聚合操作(sum、mean、max、min等),甚至自定义函数:

# 按Level-0的Name分组,对每个组执行反向expanding求和
reverse_expanding_result = df.groupby(level='Name').apply(
    lambda group: 
        # 1. 反转组内的行顺序(从最后一行开始往前)
        group.iloc[::-1]
        # 2. 执行普通的expanding聚合(这里用sum,可替换为mean/max/min等)
        .expanding().sum()
        # 3. 再次反转行顺序,恢复原时间序列的顺序
        .iloc[::-1]
)

代码解释:

  • groupby(level='Name'):将DataFrame按Level-0索引(Name字段)拆分,每个组对应一个类别(A/B/C)的时间序列。
  • group.iloc[::-1]:把当前组的行反转,让最后一行变成第一行,这样后续的expanding就相当于从原数据的末尾开始累积。
  • .expanding().sum():对反转后的序列执行正向expanding求和(你可以把sum()换成任意需要的聚合函数,比如mean()、max())。
  • 最后一次iloc[::-1]:把计算结果反转回来,恢复原数据的时间顺序,此时每行的值就是从当前行到该组最后一行的累积值。

方法2:针对求和的高效写法(用cumsum)

如果你的需求只是累积求和,那么可以用cumsum()替代expanding().sum(),速度会更快:

reverse_expanding_sum = df.groupby(level='Name').apply(
    lambda group: group.iloc[::-1].cumsum().iloc[::-1]
)

这个代码的效果和方法1完全一致,但cumsum()是专门的累积求和函数,性能更优。

验证结果

比如查看'A'组的计算结果:

print(reverse_expanding_result.loc['A'])

你会看到每行的Vals值是从当前日期到该组最后一个日期的累积求和(自动忽略NaN值)。

扩展说明

如果需要指定最小有效数据量(比如至少1个非NaN值才计算),可以在expanding()中添加min_periods参数:

# 确保至少有1个非NaN值才返回结果
reverse_expanding_result = df.groupby(level='Name').apply(
    lambda group: group.iloc[::-1].expanding(min_periods=1).mean().iloc[::-1]
)

内容的提问来源于stack exchange,提问作者feetwet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:41:39