如何在Pandas DataFrame中按ID将行转列为多值列?
Pandas按ID将行转换为多列的解决方案
问题说明
原始DataFrame:
id val 0 abc_1 5 1 abc_1 3 2 abc_1 7 3 abc_2 12 4 abc_2 6 5 abc_2 9 ...
期望将同一ID的多行值转为多列,输出如下:
id val1 val2 val3 0 abc_1 5 3 7 1 abc_2 12 6 9
尝试通过全局索引生成group列后使用pivot:
df['group'] = (df.index // 3) + 1
得到中间结果:
id val group 0 abc_1 5 1 1 abc_1 3 1 2 abc_1 7 1 3 abc_2 12 2 4 abc_2 6 2 5 abc_2 9 2
但pivot后出现大量空值,未达到预期效果。
解决方案
问题根源
之前的group列是基于全局索引计算的,若后续数据中存在ID的行数不等于3的情况,会导致分组逻辑失效,pivot时产生大量空值。正确思路是按ID分组后,为每个组内的行分配独立序号,再进行转置操作。
方案1:groupby+cumcount+pivot
import pandas as pd # 为每个ID组内的行生成从1开始的序号 df['seq'] = df.groupby('id').cumcount() + 1 # 执行pivot转置 result = df.pivot(index='id', columns='seq', values='val').reset_index() # 重命名列名为val1、val2... result.columns = ['id'] + [f'val{i}' for i in result.columns[1:]]
方案2:groupby+agg+列表展开
适合已知每个ID固定对应3个值的场景:
# 按ID分组,将val聚合为列表 result = df.groupby('id')['val'].agg(list).reset_index() # 将列表拆分为多列 result = pd.concat([result['id'], pd.DataFrame(result['val'].tolist(), columns=['val1','val2','val3'])], axis=1)
方案3:groupby+cumcount+unstack
与方案1原理一致,用unstack替代pivot:
df['seq'] = df.groupby('id').cumcount() + 1 # 设置双索引后unstack转置 result = df.set_index(['id', 'seq'])['val'].unstack().reset_index() # 重命名列名 result.columns = ['id'] + [f'val{i}' for i in result.columns[1:]]
内容的提问来源于stack exchange,提问作者Reut
相关产品推荐
相关产品推荐

