Pandas多层索引下如何实现二维联合反向累计和计算
二维联合反向累计和实现方案
你需要计算的是二维相空间的二维后缀和,即每个坐标点累加所有横、纵坐标都大于等于自身的点的取值,不需要写显式循环,基于你已经在用的反向cumsum逻辑,做两次维度的反向累计即可实现。
前置准备
计算前必须先把DataFrame按v1升序、v2升序排序,乱序会直接导致计算结果错误。
# 排序后重置索引,避免索引错位 df = df.sort_values(['v1', 'v2'], ascending=[True, True]).reset_index(drop=True)
方法1:两次分组cumsum(适合规整网格数据)
如果你的v1、v2是完整的网格组合(每个v1对应所有v2取值,和你给出的示例结构一致),直接两次反向分组累计即可,性能最好:
# 第一步:在每个v1分组内,计算v2维度的反向累计和 df['temp_col'] = df.loc[::-1].groupby('v1')['value'].cumsum()[::-1] # 第二步:在每个v2分组内,计算v1维度的反向累计和,即为最终结果 df['output'] = df.loc[::-1].groupby('v2')['temp_col'].cumsum()[::-1] # 删除临时列 df.drop(columns='temp_col', inplace=True)
方法2:透视表计算(适合有缺失组合的非规整数据)
如果你的v1、v2存在缺失的组合(不是每个v1都覆盖所有v2取值),用透视转宽表计算二维后缀和再转回长表的方法更稳妥,不会因为缺行漏算:
# 转成v1为行索引、v2为列索引的宽表,缺失组合的取值填0 pivot_tbl = df.pivot(index='v1', columns='v2', values='value').fillna(0) # 先把行列都倒序,连续做两次轴向cumsum,再把行列顺序转回原顺序,得到全量二维后缀和 suffix_sum_tbl = pivot_tbl.loc[::-1, ::-1].cumsum(axis=0).cumsum(axis=1).loc[::-1, ::-1] # 把计算结果合并回原DataFrame df = df.merge(suffix_sum_tbl.stack().rename('output'), on=['v1', 'v2'])
结果验证
以上两种方法跑你提供的示例数据,输出完全匹配预期:
| v1 | v2 | value | output |
|---|---|---|---|
| 1 | 1 | 1 | 9 |
| 1 | 2 | 1. | 6. |
| 1 | 3 | 1 | 3. |
| 2 | 1 | 1. | 6. |
| 2 | 2 | 1. | 4. |
| 2 | 3. | 1. | 2. |
| 3 | 1 | 1. | 3. |
| 3 | 2 | 1. | 2. |
| 3 | 3 | 1. | 1. |
计算逻辑很直观:第一次cumsum先把同一v1下所有v2更大的值累加完,第二次cumsum再把同一v2下所有v1更大的累加结果做累加,两次计算刚好覆盖所有v1'>=v1 且 v2'>=v2的取值。
内容的提问来源于stack exchange,提问作者D. Antony
相关产品推荐
相关产品推荐

