pandas DataFrame melt操作方法及常见使用场景解决方案
Pandas DataFrame melt 操作通用指南
在pandas相关的提问中,经常能看到用户咨询DataFrame的melt操作问题,但现有问题大多过于特定或缺少通用说明,本文将明确说明以下三点核心内容:
- melt是什么?
- 如何使用melt?
- 什么时候需要使用melt?
核心概念说明
- melt是什么:melt是pandas提供的宽表转长表的操作,也叫“反透视”操作,可以将指定的多列数据转为行,同时保留固定列的数值,实现表结构的行列转换。
- 如何使用melt:核心调用格式为
pd.melt(df, id_vars=None, value_vars=None, var_name=None, value_name='value'),各参数作用如下:id_vars:指定转换过程中保持不变的列value_vars:指定需要转为行的列,默认会使用所有未被指定为id_vars的列var_name:指定存储原列名的新列的列名value_name:指定存储原列值的新列的列名
- 什么时候需要使用melt:当你需要将多个同类型的列转为行,方便后续分组统计、可视化、或者适配其他数据处理逻辑时,就可以使用melt操作。
演示数据集
本次演示使用随机生成的学生年龄、各科成绩数据集,结构如下:
import pandas as pd df = pd.DataFrame({ 'Name': ['Bob', 'John', 'Foo', 'Bar', 'Alex', 'Tom'], 'Math': ['A+', 'B', 'A', 'F', 'D', 'C'], 'English': ['C', 'B', 'B', 'A+', 'F', 'A'], 'Age': [13, 16, 16, 15, 15, 13] })
输出的原始表结构:
Name Math English Age 0 Bob A+ C 13 1 John B B 16 2 Foo A B 16 3 Bar F A+ 15 4 Alex D F 15 5 Tom C A 13
常见问题解答
问题1:将科目列转为行,保留学生姓名、年龄,同时对应展示科目和对应成绩
需求:把Math、English两个科目列转为行,保留Name、Age两列不变,新增Subject列存储科目名,Grade列存储对应成绩。
实现代码:
res = df.melt( id_vars=['Name', 'Age'], var_name='Subject', value_name='Grade' )
问题2:仅保留Math科目的melt操作
需求:和问题1逻辑一致,但仅转换Math列,过滤掉English列的数据。
实现代码:
res = df.melt( id_vars=['Name', 'Age'], value_vars=['Math'], var_name='Subject', value_name='Grades' )
说明:通过value_vars参数指定仅需要转为行的列,其他未指定的非id列会被自动过滤。
问题3:melt后按成绩分组,拼接对应学生姓名和科目
需求:melt转换后按成绩分组,将同成绩对应的学生姓名、对应科目分别按顺序用逗号拼接。
实现代码:
# 先执行melt转换,提取姓名、科目、成绩三列 melted = df.melt(id_vars=['Name'], value_vars=['Math', 'English'], var_name='Subject') # 按成绩分组后拼接字符串 res = melted.groupby('value', as_index=False).agg( Name=('Name', ','.join), Subjects=('Subject', ','.join) ).sort_values('value')
问题4:melt长表逆操作还原为原始宽表
需求:已知melt后的长表由代码df = df.melt(id_vars=['Name', 'Age'], var_name='Subject', value_name='Grades')生成,需要将其还原为初始的宽表结构。
实现代码:
# 先构造题目给定的melt长表 melted = df.melt(id_vars=['Name', 'Age'], var_name='Subject', value_name='Grades') # 使用pivot方法还原宽表 res = melted.pivot(index=['Name', 'Age'], columns='Subject', values='Grades').reset_index().rename_axis(columns=None)
问题5:按学生姓名分组,拼接每个学生的科目和成绩为字符串
需求:melt转换后按学生姓名分组,将每个学生的所有科目、对应成绩分别用逗号拼接为字符串。
实现代码:
# 先执行melt转换 melted = df.melt(id_vars=['Name', 'Age'], var_name='Subject', value_name='Grades') # 按姓名分组拼接 res = melted.groupby('Name', as_index=False).agg( Subject=('Subject', ','.join), Grades=('Grades', ','.join) ).sort_values('Name')
问题6:全量melt,输出仅包含列名和对应值两列的结构
需求:将DataFrame所有列都转为值,最终输出仅包含原列名、原列值两列的结构。
实现代码:
res = df.melt(var_name='Column', value_name='Value')
说明:不指定id_vars参数时,所有列都会被转为行,最终生成两列分别存储原列名和原列值。
内容的提问来源于stack exchange,提问作者U13-Forward
相关产品推荐
相关产品推荐

