Pandas构造含列表列的多级索引DataFrame避免非列表列重复
可行实现方案
核心逻辑是先完成E列的展开,再通过原始行的分组标记,仅保留同组首行的A-D列值,其余行对应列置空即可,不需要复杂结构就能避免重复统计问题。
方法1:列置空方案(最贴合展示+统计需求)
不要在explode时直接加ignore_index=True,先保留原始行索引作为分组依据,处理完再重置索引:
import pandas as pd # 先执行E列展开,保留原始行索引 df_exploded = df.explode('E') # 标记同一原始行展开出的非首行 blank_mask = df_exploded.groupby(level=0).cumcount() > 0 # 将非首行的A-D列置为空值 df_exploded.loc[blank_mask, ['A','B','C','D']] = pd.NA # 按需重置索引 df_result = df_exploded.reset_index(drop=True)
处理后的效果:
- 原始行E列有N个元素就展开为N行,首行保留完整A-D值,剩下N-1行A-D列为空
- 空列表的E列会展开为1行,A-D值正常保留,E列为空
- 后续对A-D列做计数、求和等统计时,pandas会自动跳过空值,完全不会出现重复计算的问题,和原始DataFrame的A-D列统计结果完全一致
方法2:多级索引方案(适合需要保留全量关联数据的场景)
如果不想修改原列值,也可以用多级索引区分原始行和展开的子行,统计时按原始行维度去重计算即可:
df_exploded = df.explode('E') # 给每个原始行下的展开子项加序号 df_exploded['sub_row'] = df_exploded.groupby(level=0).cumcount() # 设置两级索引:第一级是原始行号,第二级是展开子项序号 df_multi = df_exploded.set_index('sub_row', append=True)
使用时如果要统计A-D列的指标,只需要先按第一级索引去重取数即可,不会重复计算:
# 示例:统计A列总和,和原始df结果一致 a_sum = df_multi.index.droplevel(1).drop_duplicates().map(df['A']).sum()
注意:不要直接用
explode(ignore_index=True)的返回结果做统计,该方法会把所有非展开列的值全量复制到展开后的每一行,必然导致重复计数。
内容的提问来源于stack exchange,提问作者Shannah
相关产品推荐
相关产品推荐

