使用Pandas groupby与agg的结果误解及相关问题咨询
问题描述
现有如下结构的DataFrame:
| ID1 | ID2 | location1 | location2 | degree |
|---|---|---|---|---|
| S5 | S10 | Nice | Paris | 1 |
| S9 | S6 | Nice | Paris | 6 |
| S9 | S10 | Nice | Paris | 6 |
| S11 | S12 | Rome | Paris | 6 |
| S14 | S11 | Marseille | Rome | 6 |
| S15 | S11 | Les Brég | Rome | 6 |
| S11 | S16 | Rome | Paris | 6 |
| S13 | S11 | Paris | Rome | 6 |
| S7 | S8 | Batz | Nice | 1 |
需求是按degree、location1、location2分组,将ID1和ID2聚合为列表,执行以下代码后遇到两个问题:
df_merge = df_merge.groupby(['degree','location1','location2']).agg({'ID1': lambda x: x.tolist(),'ID2': lambda x: x.tolist()},axis=1)
疑问:
- 如何让
location1与location2的无序组合(如Nice&Paris和Paris&Nice)合并为同一分组,而非分为两行; - 分组后的
degree、location1、location2为何与ID1、ID2不在同一行,同时无法理解DataFrame转列表后的结构。
解决方案
1. 处理无序地点分组
核心思路是生成标准化的地点对键,将无序的地点组合转化为统一标识,以此作为分组依据:
import pandas as pd # 生成排序后的地点元组作为分组键(确保Nice&Paris和Paris&Nice生成相同的键) df_merge['location_pair'] = df_merge.apply(lambda row: tuple(sorted([row['location1'], row['location2']])), axis=1) # 按degree和标准化地点键分组,聚合ID1、ID2为列表,同时重置索引将分组列转为普通列 df_result = df_merge.groupby(['degree', 'location_pair']).agg( ID1=('ID1', list), ID2=('ID2', list) ).reset_index() # 可选:将标准化地点键拆分为两列,替换原location列 df_result[['location1', 'location2']] = pd.DataFrame(df_result['location_pair'].tolist(), index=df_result.index) df_result = df_result.drop('location_pair', axis=1)
通过排序生成统一的地点对键,所有无序的地点组合会被归为同一分组。
2. 分组列与聚合列的显示问题及结构说明
- 不在同一行的原因:
groupby默认会将分组列设置为DataFrame的索引,所以degree、location相关列会显示在索引区域,而ID1、ID2是数据列。使用reset_index()方法可将索引还原为普通列,让所有列显示在同一行。 - 聚合后列表结构说明:
ID1和ID2列的每个单元格都是Python列表,包含对应分组下所有的ID1/ID2值。比如degree=6、地点对为(Paris, Rome)的分组,ID1会是['S11', 'S11', 'S13'],ID2会是['S12', 'S16', 'S11'],对应原表中所有Paris和Rome组合的行数据。
内容的提问来源于stack exchange,提问作者Pierre
相关产品推荐
相关产品推荐

