Pandas DataFrame转换:如何实现unpivot(逆透视)操作?
当然可以用逆透视实现这个转换!
你的需求是把宽表结构的DataFrame转换成标准的长表结构,逆透视(Unpivot)正是干这个的活儿~在Pandas里,有两个常用方法可以轻松搞定:wide_to_long(适合列名有规律的场景)和melt(更通用的方法)。
先构造你的原始数据
首先我们先还原你给出的DataFrame:
import pandas as pd df = pd.DataFrame({ 'commune': ['A', 'B', 'C'], 'nuance_1': ['X', 'X', 'Z'], 'votes_1': [12, 10, 7], 'nuance_2': ['Y', 'Y', 'X'], 'votes_2': [20, 5, 2], 'nuance_3': ['Z', None, None], 'votes_3': [5, None, None] })
方法1:用wide_to_long(最贴合你的列名结构)
因为你的列都是nuance_n和votes_n的命名规律,wide_to_long专门处理这种带序号后缀的宽表,代码非常简洁:
# 执行逆透视操作 df_long = pd.wide_to_long( df, stubnames=['nuance', 'votes'], # 指定要拆分的列前缀 i='commune', # 保留的唯一标识列 j='seq', # 拆分后生成的序号列(可以随便命名) sep='_' # 列名里的分隔符 ).dropna() # 去掉空值行(比如B、C的第三组数据是空的) # 整理索引和列顺序 df_long = df_long.reset_index(drop=True)[['commune', 'nuance', 'votes']]
执行后得到的结果就是你想要的结构:
| commune | nuance | votes |
|---|---|---|
| A | X | 12 |
| A | Y | 20 |
| A | Z | 5 |
| B | X | 10 |
| B | Y | 5 |
| C | Z | 7 |
| C | X | 2 |
方法2:用melt(更通用的逆透视方法)
如果你的列名没有那么规整,melt是更通用的选择。我们可以分别对nuance和votes列做逆透视,再合并结果:
# 拆分nuance列 nuance_df = df.melt( id_vars='commune', value_vars=['nuance_1', 'nuance_2', 'nuance_3'], var_name='seq', value_name='nuance' ) # 拆分votes列 votes_df = df.melt( id_vars='commune', value_vars=['votes_1', 'votes_2', 'votes_3'], var_name='seq', value_name='votes' ) # 合并并清理数据 df_long = pd.merge(nuance_df, votes_df, on=['commune', 'seq']) \ .dropna() \ .drop('seq', axis=1) \ .sort_values('commune') \ .reset_index(drop=True)
这个方法也能得到完全一样的结果,只是步骤稍多一点。
总结
完全可以通过逆透视实现这个转换!Pandas的这两个方法都是专门为宽表转长表设计的,根据你的列名结构选择对应的方法就好~
内容的提问来源于stack exchange,提问作者Fabrice BOUCHAREL
相关产品推荐
相关产品推荐

