如何在Pandas中按Id合并同实体行数据?Groupby是否适用?
Pandas 数据重塑:按Id聚合food与hazard字段
问题描述
我有如下Pandas DataFrame:
import pandas as pd data = {'Id':["A", "A", "A", "B", "B","B"], 'extraction': ["apple", "cherry", "alfatoxin", "ethyl", "glyphosate", "pasta"], "entities": ["food", "food", "hazard", "hazard", "hazard", "food"]} df = pd.DataFrame(data)
原始数据展示:
Id extraction entities 0 A apple food 1 A cherry food 2 A alfatoxin hazard 3 B ethyl hazard 4 B glyphosate hazard 5 B pasta food
期望得到的输出结果:
Id food hazards 0 A [apple, cherry] alfatoxin 1 B pasta [ethyl, glyphosate]
请问如何在Pandas中实现该需求?使用groupby是否是合适的方案?
解决方案
使用groupby是完全合适的方案,甚至是这类聚合需求的标准做法。可以通过分组+透视的组合操作实现,具体步骤如下:
方法1:分步实现
- 按
Id和entities分组,将每组的extraction值合并为列表:
grouped = df.groupby(['Id', 'entities'])['extraction'].agg(list).reset_index()
这一步得到的中间结果:
Id entities extraction 0 A food [apple, cherry] 1 A hazard [alfatoxin] 2 B food [pasta] 3 B hazard [ethyl, glyphosate]
- 将
entities的取值转为列名(透视操作):
result = grouped.pivot(index='Id', columns='entities', values='extraction').reset_index()
- 调整列名,并把长度为1的列表转为单个值:
# 重命名列 result.columns = ['Id', 'food', 'hazards'] # 处理单个元素的列表 result['food'] = result['food'].apply(lambda x: x[0] if len(x) == 1 else x) result['hazards'] = result['hazards'].apply(lambda x: x[0] if len(x) == 1 else x)
最终得到的结果就和期望一致。
方法2:链式简化操作
可以把上述步骤合并为一行链式代码,更简洁:
result = (df.groupby(['Id', 'entities'])['extraction'] .agg(list) .unstack('entities') .reset_index() .rename(columns={'hazard': 'hazards'}) .applymap(lambda x: x[0] if len(x) == 1 else x))
关键说明
groupby的作用是按Id+entities的组合分组,确保同一Id下的food和hazard分别聚合agg(list)用来把每组的extraction值打包成列表unstack(或pivot)实现从长表到宽表的转换,把food和hazard转为单独的列- 最后的
applymap处理单个元素的列表,让结果格式更贴合需求
内容的提问来源于stack exchange,提问作者Dawn.Sahil
相关产品推荐
相关产品推荐

