如何对DataFrame进行行透视,将宽表转换为长表?
Pandas 宽表转长表实现方案
问题场景
原始DataFrame为宽表格式,每行对应一个id的多组测量值、时间值及固定参数:
# 原始数据结构示例 id meas1 meas2 meas3 t1 t2 t3 p 0 1 meas11 meas12 meas13 t11 t12 t13 p1 1 2 meas21 meas22 meas23 t21 t22 t23 p2
需要转换为长表格式,每个id的每组测量+时间+参数单独成一行:
# 目标数据结构示例 id meas t p 0 1 meas11 t11 p1 1 1 meas12 t12 p1 2 1 meas13 t13 p1 3 2 meas21 t21 p2 4 2 meas22 t22 p2 5 2 meas23 t23 p2
实现方法
方法1:使用pd.wide_to_long(推荐,适合列名有规律的场景)
这个方法专门处理带分组后缀的宽表,直接匹配列名的前缀与后缀:
import pandas as pd # 构造原始DataFrame df = pd.DataFrame({ 'id': [1, 2], 'meas1': ['meas11', 'meas21'], 'meas2': ['meas12', 'meas22'], 'meas3': ['meas13', 'meas23'], 't1': ['t11', 't21'], 't2': ['t12', 't22'], 't3': ['t13', 't23'], 'p': ['p1', 'p2'] }) # 执行转换 result = pd.wide_to_long( df, stubnames=['meas', 't'], # 列名前缀 i=['id', 'p'], # 保持不变的标识符列 j='group', # 后缀对应的分组名(可自定义) sep='' # 列名前缀与后缀的分隔符,此处无分隔符设为空 ).reset_index() # 可选:删除不需要的group列 result = result.drop('group', axis=1)
方法2:使用pd.melt分两次转换再合并
如果列名规律不明显,可分别处理meas和t列后合并结果:
import pandas as pd # 构造原始DataFrame(同方法1) df = pd.DataFrame({ 'id': [1, 2], 'meas1': ['meas11', 'meas21'], 'meas2': ['meas12', 'meas22'], 'meas3': ['meas13', 'meas23'], 't1': ['t11', 't21'], 't2': ['t12', 't22'], 't3': ['t13', 't23'], 'p': ['p1', 'p2'] }) # 转换meas列 meas_melt = df.melt( id_vars=['id', 'p'], value_vars=['meas1', 'meas2', 'meas3'], var_name='meas_group', value_name='meas' ) # 转换t列 t_melt = df.melt( id_vars=['id', 'p'], value_vars=['t1', 't2', 't3'], var_name='t_group', value_name='t' ) # 提取分组编号并合并结果 meas_melt['group'] = meas_melt['meas_group'].str.extract('(\d+)') t_melt['group'] = t_melt['t_group'].str.extract('(\d+)') result = pd.merge(meas_melt, t_melt, on=['id', 'p', 'group']).drop(['meas_group', 't_group', 'group'], axis=1)
两种方法最终都会得到目标的长表格式。
内容的提问来源于stack exchange,提问作者zahra elhamraoui
相关产品推荐
相关产品推荐

