如何让pandas的wide_to_long()识别列名末尾的存根而非开头?
解决列名格式为「年份_存根」的宽表转长表问题
针对你遇到的列名是2010_A(weekly)这种「年份在前、存根在后」的格式,pd.wide_to_long确实没有直接参数支持反向识别存根,但可以通过两种简单方法实现需求:
方法一:先重命名列,再用wide_to_long
先把列名的年份和存根位置调换,变成wide_to_long能识别的「存根_年份」格式,再调用函数:
import numpy as np import pandas as pd np.random.seed(0) df = pd.DataFrame({'2010_A(weekly)': np.random.rand(3), '2011_A(weekly)': np.random.rand(3), '2010_B(weekly)': np.random.rand(3), '2011_B(weekly)': np.random.rand(3), 'X' : np.random.randint(3, size=3)}) df['id'] = df.index # 重命名列:将"年份_存根"转为"存根_年份" df_renamed = df.rename(columns=lambda x: '_'.join(x.split('_', 1)[::-1]) if '_' in x else x) # 调用wide_to_long result = pd.wide_to_long(df_renamed, ['A(weekly)', 'B(weekly)'], i='id', j='year', sep='_') # 重置索引得到目标列顺序 result = result.reset_index()[['id', 'year', 'X', 'A(weekly)', 'B(weekly)']]
方法二:用melt+提取列信息+pivot实现
如果存根名称里可能包含下划线,这种方法更通用:
import numpy as np import pandas as pd np.random.seed(0) df = pd.DataFrame({'2010_A(weekly)': np.random.rand(3), '2011_A(weekly)': np.random.rand(3), '2010_B(weekly)': np.random.rand(3), '2011_B(weekly)': np.random.rand(3), 'X' : np.random.randint(3, size=3)}) df['id'] = df.index # 第一步:将宽表melt为长表,保留id和X作为标识 melted = df.melt(id_vars=['id', 'X'], var_name='col_name', value_name='value') # 第二步:从列名中提取年份和存根 melted[['year', 'stub']] = melted['col_name'].str.extract(r'(\d+)_(.+)', expand=True) # 第三步:pivot将存根转为列,得到目标格式 result = melted.pivot(index=['id', 'year', 'X'], columns='stub', values='value').reset_index() result.columns.name = None # 去掉列名的索引标识
两种方法最终都能得到包含id, year, X, A(weekly), B(weekly)的长格式DataFrame。
内容的提问来源于stack exchange,提问作者John Hadish
相关产品推荐
相关产品推荐

