如何使用Pandas将原始数据重排为报表格式(含多限额场景)
Pandas 实现分层报表格式转换
一、基础场景实现
针对单个客户对应统一限额的场景,我们需要生成「客户汇总行+账户明细行」的分层结构:汇总行展示客户信息、总余额,明细行展示单个账户信息。
实现代码
import pandas as pd # 原始数据 d = {'Customer Name': ['A', 'A', 'B', 'C', 'C', 'C'], 'ID_NO': ['AA', 'AA', 'BB', 'CC', 'CC', 'CC'], 'Account Number': ['123456', '123457', '234567', '345678', '345679', '345680'], 'Limit': [1000, 1000, 900, 1200, 1200, 1200], 'Balance': [400, 600, 800, 300, 400, 200]} df = pd.DataFrame(data=d) # 生成客户汇总行:按客户+ID分组,计算总余额,保留限额值 summary_rows = df.groupby(['Customer Name', 'ID_NO'], as_index=False).agg( Limit=('Limit', 'first'), Balance=('Balance', 'sum') ) # 分配排序标识,确保汇总行排在对应明细行前 summary_rows['sort_key'] = df.groupby(['Customer Name']).ngroup() * 2 # 生成账户明细行:重命名账户列为客户名,清空ID和限额列 detail_rows = df[['Account Number', 'Balance']].rename(columns={'Account Number': 'Customer Name'}) detail_rows['ID_NO'] = '' detail_rows['Limit'] = '' # 分配明细行排序标识,跟在对应汇总行后 detail_rows['sort_key'] = df.groupby(['Customer Name']).ngroup() * 2 + 1 # 合并数据并排序,整理列顺序 result = pd.concat([summary_rows, detail_rows]).sort_values('sort_key').drop('sort_key', axis=1) result = result[['Customer Name', 'ID_NO', 'Limit', 'Balance']].reset_index(drop=True) print(result)
输出说明
生成的结果与你期望的df2结构完全一致:每个客户的汇总行在前,显示客户名称、ID、限额及总余额;后续行显示对应账户号,ID和限额列为空,余额为单个账户数值。
二、多限额场景实现
当单个客户存在多个Limit Number时,需要按客户-限额组生成分层结构:每个限额组对应一个汇总行,下方是该组的账户明细。
实现代码
import pandas as pd # 多限额原始数据 d = {'Customer Name': ['A', 'A', 'B', 'C', 'C', 'C'], 'ID_NO': ['AA', 'AA', 'BB', 'CC', 'CC', 'CC'], 'Limit Number': ['AAA', 'AAA', 'BBB', 'CCC', 'CCC', 'CCD'], 'Account Number': ['123456', '123457', '234567', '345678', '345679', '345680'], 'Limit': [1000, 1000, 900, 1200, 1200, 1500], 'Balance': [400, 600, 800, 300, 400, 600]} df = pd.DataFrame(data=d) # 生成限额组汇总行:按客户+ID+限额编号分组,计算组内总余额,保留限额值 summary_rows = df.groupby(['Customer Name', 'ID_NO', 'Limit Number'], as_index=False).agg( Limit=('Limit', 'first'), Balance=('Balance', 'sum') ) # 分配排序标识:每个限额组对应唯一编号,汇总行用偶数编号 summary_rows['sort_key'] = df.groupby(['Customer Name', 'Limit Number']).ngroup() * 2 # 生成账户明细行:替换客户名为账户号,清空ID和限额列 detail_rows = df.copy() detail_rows['Customer Name'] = detail_rows['Account Number'] detail_rows['ID_NO'] = '' detail_rows['Limit'] = '' # 分配明细行排序标识:对应限额组的奇数编号,确保跟在汇总行后 detail_rows['sort_key'] = df.groupby(['Customer Name', 'Limit Number']).ngroup() * 2 + 1 detail_rows = detail_rows[['Customer Name', 'ID_NO', 'Limit', 'Balance', 'sort_key']] # 合并并排序数据,整理最终列顺序 result = pd.concat([summary_rows, detail_rows]).sort_values('sort_key').drop('sort_key', axis=1) result = result[['Customer Name', 'ID_NO', 'Limit', 'Balance']].reset_index(drop=True) print(result)
逻辑说明
- 通过
groupby(['Customer Name', 'Limit Number']).ngroup()给每个客户下的限额组分配唯一组号,确保排序时组内顺序正确 - 汇总行使用组号2,明细行使用组号2+1,保证每组汇总行始终在其明细行之前
- 最终合并后按
sort_key排序,得到符合需求的分层报表结构
内容的提问来源于stack exchange,提问作者hoa tran
相关产品推荐
相关产品推荐

