Pandas如何使用melt处理多列 实现宽表到指定结构长表转换
Pandas多列宽表转长表实现方案
你的需求是按P1/P2/P3的分组逻辑,把同组的P/x/y三列从列转行,属于典型的带分组标识的宽转长场景,以下是基于melt逻辑的具体实现:
第一步:构造原始测试数据
先复现你给出的输入DataFrame:
import pandas as pd df = pd.DataFrame({ 'id': ['_1', '_2'], 'P1': ['a', 'd'], 'x1': [1, 4], 'y1': ['aa', 'dd'], 'P2': ['b', 'e'], 'x2': [2, 5], 'y2': ['bb', 'ee'], 'P3': ['c', 'f'], 'x3': [3, 6], 'y3': ['cc', 'ff'] })
方法1:纯melt基础操作实现
完全基于melt逆透视+透视调整的逻辑实现,步骤清晰可自定义:
# 对所有非id列做逆透视,转成(key, value)的长表格式 df_melted = df.melt(id_vars='id', var_name='raw_col', value_name='value') # 拆分原始列名:末尾数字是P的序号,前面的字符是值类型(P/x/y) df_melted['prob_no'] = df_melted['raw_col'].str[-1] df_melted['value_type'] = df_melted['raw_col'].str[:-1] # 按id和P序号做透视,把三类值展开成独立列 df_result = df_melted.pivot( index=['id', 'prob_no'], columns='value_type', values='value' ).reset_index() # 整理字段格式和顺序,匹配输出要求 df_result['Probability'] = 'P' + df_result['prob_no'] df_result['id'] = df_result['id'].str.replace('_', '-') # 匹配示例里_转-的格式 df_result = df_result.rename(columns={'P': 'code', 'x': 'number', 'y': 'name'}) df_result = df_result[['id', 'Probability', 'code', 'number', 'name']].reset_index(drop=True)
执行后输出的结果和你给出的目标结构完全一致。
方法2:wide_to_long快捷实现(底层基于melt封装)
如果你的列名规则统一(同组列前缀相同、末尾为数字序号),可以直接用pandas内置的wide_to_long方法,代码更简洁:
df_result = pd.wide_to_long( df, stubnames=['P', 'x', 'y'], # 同组列的前缀 i='id', # 不需要转换的主键列 j='prob_no', # 存储序号的列名 suffix='\d+' # 匹配列名末尾的数字序号 ).reset_index() # 后续字段整理逻辑和方法1一致 df_result['Probability'] = 'P' + df_result['prob_no'].astype(str) df_result['id'] = df_result['id'].str.replace('_', '-') df_result = df_result.rename(columns={'P': 'code', 'x': 'number', 'y': 'name'}) df_result = df_result[['id', 'Probability', 'code', 'number', 'name']].reset_index(drop=True)
注:如果你的id不需要把
_替换成-,删掉对应str.replace的代码行即可。
内容的提问来源于stack exchange,提问作者Ashish
相关产品推荐
相关产品推荐

