pandas如何将多列存储的等长列表拆分为单行单值结构
Pandas实现宽表转每行单值长表的方法
你需要实现的是典型的宽表逆透视为长表的操作,源数据结构如下:
目标输出结构如下:
以下是3种可直接复用的实现方式,先构造和示例完全一致的测试数据:
import pandas as pd # 构造和示例匹配的源数据 df = pd.DataFrame({ 'Name': ['A', 'B', 'C'], 'Maths': [92, 87, 95], 'Science': [89, 94, 86], 'English': [90, 85, 91] })
方法1:使用melt()(最推荐,可读性最高)
melt是pandas专为逆透视设计的API,参数语义清晰,是这类场景的首选方案:
result = df.melt( id_vars=['Name'], # 保留不做展开的标识列,存在多个标识列直接传列表即可 var_name='Subject', # 原列名转换后对应的新列名 value_name='Marks' # 单元格值转换后对应的新列名 ) # 按Name排序、重置索引,和示例输出顺序完全对齐 result = result.sort_values('Name', ignore_index=True)
输出结果和目标结构完全一致。
方法2:使用stack()(写法最简洁)
stack是pandas的索引堆叠方法,通过将普通列转为行索引的方式实现长表转换,代码更简短:
# 先将标识列设为行索引,对剩余列做堆叠,最后重置索引还原为普通列 result = df.set_index('Name').stack().reset_index() # 重命名列匹配目标结构 result.columns = ['Name', 'Subject', 'Marks']
方法3:使用wide_to_long()(适合复杂列名场景)
如果你的列名带有固定规则(比如列名是Marks_Maths、Marks_Science这类带固定前缀的格式),可以用这个API做批量转换,简单场景也可兼容:
# 先给待展开列加统一前缀以匹配API规则 df_renamed = df.rename(columns={ 'Maths': 'Marks_Maths', 'Science': 'Marks_Science', 'English': 'Marks_English' }) result = pd.wide_to_long( df_renamed, stubnames=['Marks'], # 要提取值的列名前缀 i=['Name'], # 标识列 j='Subject', # 列名后缀转换后的新列名 sep='_', suffix=r'\w+' ).reset_index()
提示:如果源数据有多个需要保留的标识列(比如班级、学号等),只要把对应列名加入
id_vars参数(melt/wide_to_long),或者设为多层索引(stack)即可,逻辑完全通用。
内容的提问来源于stack exchange,提问作者devansh
相关产品推荐
相关产品推荐

