如何在Pandas中按客户分组将行转列为指定格式宽表
解决客户数据长表转指定宽表的问题
嘿,我来给你一个简洁可行的解决方案,刚好能匹配你想要的列结构!先回顾下你的场景:
你已经有了按Customer Number和Date排序好的DataFrame,创建代码如下:
import pandas as pd df = pd.DataFrame({ 'Customer Number':[1,1,1,2,2,3,3,3], 'Date': [2013, 2014, 2015, 2016, 2017, 2013, 2014, 2015], 'Salaries': [100, 200, 200, 300, 300, 4000, 5000, 5000] })
对应的原始长表结构:
Customer Number Date Salaries 0 1 2013 100 1 1 2014 200 2 1 2015 200 3 2 2016 300 4 2 2017 300 5 3 2013 4000 6 3 2014 5000 7 3 2015 5000
你的需求是把每个客户的日期和薪资依次转成Date 1、Salary 1、Date 2、Salary 2这类新列,得到目标宽表。
具体实现步骤
核心思路是用groupby生成每个客户的记录序号,再结合unstack重塑数据,最后调整列名和顺序:
- 给每个客户的记录加序号
先给每个客户的行标记是第几条记录(从1开始),这样后续可以区分Date 1和Date 2:
df['seq'] = df.groupby('Customer Number').cumcount() + 1
这一步后,每个客户的行都会有一个seq列,值为1、2、3(对应第1/2/3条数据)。
- 重塑数据并修改列名
把seq作为列的层级,unstack之后重命名列,让列名变成你想要的Date N、Salaries N格式:
# 把Customer Number和seq设为索引,然后unstack展开 wide_df = df.set_index(['Customer Number', 'seq']).unstack() # 重命名列,合并原列名和序号 wide_df.columns = [f'{col[0]} {col[1]}' for col in wide_df.columns] # 把Customer Number从索引变回普通列 wide_df = wide_df.reset_index()
- 调整列的顺序(可选)
如果你希望Date和Salaries是交替排列的(比如先Date1、再Salary1,接着Date2、Salary2...),可以手动调整列顺序:
# 生成有序的列名列表 max_seq = df['seq'].max() ordered_cols = [] for i in range(1, max_seq + 1): ordered_cols.append(f'Date {i}') ordered_cols.append(f'Salaries {i}') # 把Customer Number放在最前面,后面跟着有序的列 wide_df = wide_df[['Customer Number'] + ordered_cols]
最终效果
运行完上面的代码,你就能得到完全符合需求的宽表:
Customer Number Date 1 Salaries 1 Date 2 Salaries 2 Date 3 Salaries 3 0 1 2013 100 2014 200 2015 200 1 2 2016 300 2017 300 NaN NaN 2 3 2013 4000 2014 5000 2015 5000
这个方案不仅简洁,还能自动适配不同客户的记录数量——比如客户2只有2条数据,缺失的列会自动填充NaN,完全满足你的需求。
内容的提问来源于stack exchange,提问作者Mike P.
相关产品推荐
相关产品推荐

