Pandas melt自动排序结果问题:如何保留原行顺序展开列?
问题与解决
问题描述
原DataFrame结构:
col1 col2 col3 targ1 targ3 targ6 a b c 1 2 3 a c d 2 4 9
执行以下melt行转列代码:
pivot_df = (data.melt(id_vars=data.columns.difference(['targ1','targ3','targ6']),var_name='m_val', value_name='value') .assign(month=lambda d: d['m_val'].astype('str').str.extractall('(\d+)').unstack().fillna('').sum(axis=1).astype(int)) )
得到的结果中m_val被自动按顺序分组:
col1 col2 col3 m_val value a b c targ1 1 a c d targ1 2 a b c targ3 2 a c d targ3 4 a b c targ6 3 a c d targ6 9
需求是按原DataFrame行顺序逐行展开targ列,即先处理第一行的targ1、targ3、targ6,再处理第二行的对应列,期望结果:
col1 col2 col3 m_val value a b c targ1 1 a b c targ3 2 a b c targ6 3 a c d targ1 2 a c d targ3 4 a c d targ6 9
尝试设置ignore_index=False时触发报错:
ValueError: Index contains duplicate entries, cannot reshape
问题原因
melt自动分组
m_val的原因:
pandas的melt函数默认按value_vars的列名顺序(即targ1→targ3→targ6)堆叠同一列的所有行,而非按原DataFrame的行顺序逐行展开列,最终呈现出m_val按顺序分组的效果。ignore_index=False报错的原因:
设置ignore_index=False后,melt会保留原DataFrame的索引,但原索引会因每行被拆分为3行而重复出现,导致索引存在重复项,无法完成重塑操作,因此触发报错。
解决方法
通过给原DataFrame添加临时行序号标识,在melt后按行序号排序,即可实现按原行顺序逐行展开targ列的需求:
代码实现
# 给原DataFrame添加行序号列 data['row_id'] = data.index # 执行melt并按行序号排序 pivot_df = (data.melt(id_vars=['col1', 'col2', 'col3', 'row_id'], value_vars=['targ1', 'targ3', 'targ6'], # 指定列顺序与原DataFrame一致 var_name='m_val', value_name='value') .assign(month=lambda d: d['m_val'].str.extract('(\d+)').astype(int)) # 简化数字提取逻辑 .sort_values(['row_id', 'm_val']) # 先按行序号保证原行顺序,再按m_val保证每行的列顺序 .drop('row_id', axis=1) # 删除临时行序号列 .reset_index(drop=True) ) # 可选:将m_val替换为纯数字 pivot_df['m_val'] = pivot_df['month']
执行后得到的结果:
col1 col2 col3 m_val value month a b c 1 1 1 a b c 3 2 3 a b c 6 3 6 a c d 1 2 1 a c d 3 4 3 a c d 6 9 6
内容的提问来源于stack exchange,提问作者Obiii
相关产品推荐
相关产品推荐

