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

Pandas多层索引DataFrame重索引:补全指定层级缺失月份

解决方案:补全MultiIndex中的月份层级且保留有效组合

要实现补全指定索引层级(月份)的所有取值,同时避免生成无效的Grouping与Sub-Group组合,可以通过以下两种方式操作:


方法一:基于现有聚合结果重索引

先完成原有的聚合操作,再针对有效组合生成完整的月份索引进行重映射:

步骤1:执行原聚合操作

import numpy as np
import pandas as pd

# 原DataFrame构建逻辑
np.random.seed(5)
size = 25
dict = {'Customer':np.random.choice( ['Bob'], size),
        'Grouping': np.random.choice( ['Corn','Wheat','Soy'], size),
        'Date':np.random.choice( pd.date_range('1/1/2018','12/12/2022', freq='D'), size),
        'Data': np.random.randint(20,100, size=(size))
        }
df = pd.DataFrame(dict)

df['Sub-Group'] = np.nan
df.loc[df['Grouping'] == 'Corn', 'Sub-Group'] = np.random.choice(['White', 'Dry'], size=len(df[df['Grouping'] == 'Corn']))
df.loc[df['Grouping'] == 'Wheat', 'Sub-Group'] = np.random.choice(['SRW', 'HRW', 'SWW'], size=len(df[df['Grouping'] == 'Wheat']))
df.loc[df['Grouping'] == 'Soy', 'Sub-Group'] = np.random.choice(['Beans', 'Meal'], size=len(df[df['Grouping'] == 'Soy']))

df['Year'] = df.Date.dt.year

# 执行聚合并将Year层级转为列
grouped_df = (df.groupby(['Customer','Grouping','Sub-Group', df['Date'].dt.month, 'Year'])
              .agg(Units=('Data', 'sum'))
              .unstack()
              .fillna(0)
)

步骤2:生成有效组合+完整月份的索引

从现有聚合结果中提取有效的(Customer, Grouping, Sub-Group)组合(避免无效笛卡尔积),再为每个组合生成1-12月的完整索引:

# 获取所有有效的(Customer, Grouping, Sub-Group)唯一组合
valid_top_levels = grouped_df.index.droplevel(3).unique()

# 生成包含所有月份的完整MultiIndex
full_index = pd.MultiIndex.from_product(
    [valid_top_levels, range(1, 13)],
    names=grouped_df.index.names
)

步骤3:重索引并填充0

# 补全缺失月份,空值填充0
result = grouped_df.reindex(full_index, fill_value=0)

方法二:从源数据层面补全组合(更彻底)

如果需要确保每个年份-月份的组合都被覆盖,可以先生成所有有效组合的空记录,再与原数据合并后聚合:

# 提取原数据中的唯一维度值
unique_customers = df['Customer'].unique()
unique_group_subgroup = df[['Grouping', 'Sub-Group']].drop_duplicates()
unique_years = df['Year'].unique()

# 生成所有可能的(Customer, Grouping, Sub-Group, Year, Month)组合
full_combinations = pd.MultiIndex.from_product(
    [unique_customers, unique_group_subgroup.itertuples(index=False), unique_years, range(1,13)],
    names=['Customer', 'Grouping', 'Sub-Group', 'Year', 'Month']
).to_frame(index=False)

# 原数据添加Month列
df['Month'] = df['Date'].dt.month

# 合并原数据,空值填充0
merged_df = pd.merge(
    full_combinations,
    df[['Customer','Grouping','Sub-Group','Year','Month','Data']],
    on=['Customer','Grouping','Sub-Group','Year','Month'],
    how='left'
).fillna(0)

# 聚合并将Year转为列
result = merged_df.groupby(['Customer','Grouping','Sub-Group','Month','Year'])
                  .agg(Units=('Data','sum'))
                  .unstack(fill_value=0)

原有方法失败原因说明

  • 第一种方法:仅单独对月份层级重索引,但如果某个(Customer, Grouping, Sub-Group)组合在原数据中完全没有对应月份的记录,该组合会被忽略;且生成的rere仅包含2018年的月份,未覆盖完整的1-12月范围。
  • 第二种方法:使用pd.MultiIndex.from_product(x.index.levels)会生成所有层级的笛卡尔积,包括原数据中不存在的Grouping与Sub-Group组合(如Wheat+Dry),因此会出现无效记录。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 04:35:47