如何在Pandas中多列分组并补充缺失分组的行
问题描述
我的数据集有3个分类变量:Year(2个唯一值)、Gender(2个唯一值)、Country(2个唯一值),还有2个数值变量:Work exp(工作年限)和Salary(薪资)。这三个分类变量总共有8种(2×2×2)组合,但执行下面的分组聚合代码后,只得到了5种组合:
df.groupby(['Years','Gender','Country'])[['Salary','Work ex']].mean() df.reset_index(inplace=True)
分组后的数据如下:
| Years | Gender | Country | Salary | Work ex |
|---|---|---|---|---|
| 2010 | Male | USA | 50 | 2 |
| 2011 | Female | India | 30 | 1 |
| 2011 | Male | India | 10 | 3 |
| 2011 | Male | USA | 50 | 2 |
| 2011 | Female | USA | 80 | 2 |
我需要生成包含所有8种分类组合的行,新增行的数值字段填NA,最终效果如下:
| Years | Gender | Country | Mean Salary | Mean Work ex |
|---|---|---|---|---|
| 2010 | Male | USA | 50 | 2 |
| 2010 | Male | India | NA | NA |
| 2010 | Female | USA | NA | NA |
| 2010 | Female | India | NA | NA |
| 2011 | Female | India | 30 | 1 |
| 2011 | Male | India | 10 | 3 |
| 2011 | Male | USA | 50 | 2 |
| 2011 | Female | USA | 80 | 2 |
解决方案
方法1:补全组合后合并(适合已完成分组的情况)
如果已经得到了分组后的grouped_df,可以先生成所有分类组合,再和现有数据左连接,自动补全缺失行:
import pandas as pd # 提取三个分类变量的所有唯一值 years = grouped_df['Years'].unique() genders = grouped_df['Gender'].unique() countries = grouped_df['Country'].unique() # 生成全部8种组合 all_combinations = pd.MultiIndex.from_product( [years, genders, countries], names=['Years', 'Gender', 'Country'] ).to_frame(index=False) # 左连接现有数据,缺失数值自动填NaN full_df = all_combinations.merge(grouped_df, on=['Years', 'Gender', 'Country'], how='left') # 可选:重命名列名匹配需求 full_df.rename(columns={'Salary': 'Mean Salary', 'Work ex': 'Mean Work ex'}, inplace=True)
方法2:分组时直接保留所有组合(推荐,适合未分组的情况)
如果还没执行分组,可以先把分类变量转为Categorical类型(确保包含所有可能取值),再在groupby里加dropna=False,这样分组时会自动保留所有组合:
import pandas as pd # 把分类变量转为Categorical,指定所有可能的取值 df['Years'] = pd.Categorical(df['Years'], categories=[2010, 2011]) df['Gender'] = pd.Categorical(df['Gender'], categories=['Male', 'Female']) df['Country'] = pd.Categorical(df['Country'], categories=['USA', 'India']) # 分组聚合时保留所有组合,缺失值自动填NaN full_df = df.groupby(['Years','Gender','Country'], dropna=False)[['Salary','Work ex']].mean().reset_index() # 可选:重命名列名 full_df.rename(columns={'Salary': 'Mean Salary', 'Work ex': 'Mean Work ex'}, inplace=True)
内容的提问来源于stack exchange,提问作者RandomForest
相关产品推荐
相关产品推荐

