如何使用pd.melt等方法将示例Pandas DataFrame转为目标宽表
问题描述
现有如下示例DataFrame:
df = pd.DataFrame([['Bob', 'lunch', 70], ['Bob', 'dinner', 160], ['Sara', 'lunch', 150], ['Sara', 'dinner', 220]], columns=['Name', 'Meal', 'Cost'])
原始数据预览:
Name Meal Cost 0 Bob lunch 70 1 Bob dinner 160 2 Sara lunch 150 3 Sara dinner 220
需求为使用pd.melt或其他可行方法,将上述数据转换为如下目标结构:
Name Meal_1 Cost_1 Meal_2 Cost_2 0 Bob lunch 70 dinner 160 1 Sara lunch 150 dinner 220
解决方法
首先说明:pd.melt的功能是宽表转长表,和当前长表转宽表的需求方向相反,不需要强行使用,直接按分组生成序号后做透视转换即可,代码简洁且运行效率高:
import pandas as pd # 为每个用户名下的餐次生成1、2的递增序号,对应目标表的列名后缀 df['meal_seq'] = df.groupby('Name').cumcount() + 1 # 执行长表转宽表操作 result = df.pivot(index='Name', columns='meal_seq', values=['Meal', 'Cost']) # 调整列名格式为Meal_1、Cost_1的形式 result.columns = [f'{col}_{seq}' for col, seq in result.columns] # 将Name从索引还原为普通数据列 result = result.reset_index()
运行后输出的result和目标结构完全一致:
Name Meal_1 Cost_1 Meal_2 Cost_2 0 Bob lunch 70 dinner 160 1 Sara lunch 150 dinner 220
该写法会自动适配每个用户的餐次数量,如果后续出现用户有第3餐、第4餐的记录,会自动生成Meal_3/Cost_3等对应列,不需要手动硬编码列数。
如果你一定要在流程中加入pd.melt步骤,也可以按如下写法实现,但属于冗余操作,没有性能优势:
df['meal_seq'] = df.groupby('Name').cumcount() + 1 # 冗余的melt转换步骤 melted = df.melt(id_vars=['Name', 'meal_seq'], value_vars=['Meal', 'Cost']) result = melted.pivot(index='Name', columns=['variable', 'meal_seq'], values='value') result.columns = [f'{col}_{seq}' for col, seq in result.columns] result = result.reset_index()
内容的提问来源于stack exchange,提问作者k07224115
相关产品推荐
相关产品推荐

