如何取消pandas DataFrame自动截断,完整保留MultiIndex所有组合
解决方案
你的代码问题核心在于:groupby操作默认会过滤掉没有任何数据的索引取值,你后续从grouped_df.index.levels获取层级取值生成全量索引时,已经丢失了原数据中完全没有出现过的取值,自然无法生成对应的索引组合。按如下步骤调整即可:
方法1:提前定义全量索引取值(最稳定)
如果你明确知道每个索引层级的所有可能取值,直接手动定义后生成全量索引,完全不依赖分组后的结果:
import pandas as pd # 第一步:定义每个索引层级的所有可能取值,按索引顺序排列 index_levels = ['Channel', 'Duration', 'Designation', 'Manufacturing Class'] level_all_values = [ ['Retail'], # Channel的所有可能值 ['Month', 'Season'], # Duration的所有可能值 ['Special', 'Not Special'], # Designation的所有可能值 ['Brand', 'Generic'] # Manufacturing Class的所有可能值 ] # 第二步:分组时保留空分组,避免进一步过滤 grouped_df = df.groupby( by=index_levels, dropna=False, # 保留值为NaN的分组 observed=False # 如果是分类列,强制保留所有分类取值 )[['Total Purchases', 'Sales', 'Cost']].sum() # 第三步:用提前定义的全量取值生成MultiIndex重排,缺失值填0 full_multi_index = pd.MultiIndex.from_product(level_all_values, names=index_levels) grouped_df = grouped_df.reindex(full_multi_index, fill_value=0)
方法2:将索引列转为分类类型
如果希望直接通过列属性控制保留的取值,可以提前把索引列转为分类类型,提前指定所有可能的分类:
# 提前给每个索引列设置全部分类 df['Designation'] = pd.Categorical(df['Designation'], categories=['Special', 'Not Special']) df['Duration'] = pd.Categorical(df['Duration'], categories=['Month', 'Season']) # 其余索引列按同样逻辑设置分类 # 分组时指定observed=False,强制保留所有分类组合 grouped_df = df.groupby( by=index_levels, dropna=False, observed=False )[['Total Purchases', 'Sales', 'Cost']].sum(fill_value=0)
注:
sum的fill_value参数在pandas 2.1.0及以上版本支持,低版本可以后续再调用fillna(0)补全。
内容的提问来源于stack exchange,提问作者user16537374
相关产品推荐
相关产品推荐

