如何高效重塑DataFrame:将分组列转为HH/JJ/KK新列并保留标识列
高效重塑Pandas DataFrame的方法
当然有高效的办法啦!你这种需求属于典型的宽表转长表场景,而且你的列名规律很强(A/B/C前缀加数字后缀),用Pandas自带的工具就能轻松搞定,完全不用写复杂的循环。
我给你两种高效的实现方式,你可以根据自己的习惯选择:
方法一:利用filter+concat快速分组合并
这种方法最直接,利用列名的前缀规律,批量提取每组数据并合并,效率非常高:
首先先构造你的示例DataFrame(方便测试):
import pandas as pd df = pd.DataFrame({ 'A1': ['a1', 'a4', 'a7'], 'A2': ['a2', 'a5', 'a8'], 'A3': ['a3', 'a6', 'a9'], 'B1': ['b1', 'b4', 'b7'], 'B2': ['b2', 'b5', 'b8'], 'B3': ['b3', 'b6', 'b9'], 'C1': ['c1', 'c4', 'c7'], 'C2': ['c2', 'c5', 'c8'], 'C3': ['c3', 'c6', 'c9'], 'TT': [11, 14, 17], 'YY': [12, 15, 18], 'ZZ': [13, 16, 19] })
然后执行重塑操作:
# 遍历A/B/C三个前缀,分别提取对应列并重命名,再合并TT/YY/ZZ列 result = pd.concat([ df.filter(regex=f'^{prefix}') # 提取当前前缀的所有列(比如A1/A2/A3) .rename(columns={f'{prefix}1': 'HH', f'{prefix}2': 'JJ', f'{prefix}3': 'KK'}) # 重命名为目标列名 .join(df[['TT', 'YY', 'ZZ']]) # 合并原有的TT/YY/ZZ列 for prefix in ['A', 'B', 'C'] ], ignore_index=True) # 合并后重置索引
执行完后,result就是你想要的结构啦!这种方法全程用Pandas的向量化操作,没有逐行循环,数据量越大越能体现效率优势。
方法二:用wide_to_long实现(适合更复杂的列名规律)
如果你的列名规律更复杂,或者需要更灵活的转换,可以用Pandas的wide_to_long函数,不过需要先调整一下列名:
# 先把原列名重命名为「前缀_目标列名」的格式 df_renamed = df.rename(columns={ 'A1': 'A_HH', 'A2': 'A_JJ', 'A3': 'A_KK', 'B1': 'B_HH', 'B2': 'B_JJ', 'B3': 'B_KK', 'C1': 'C_HH', 'C2': 'C_JJ', 'C3': 'C_KK' }) # 使用wide_to_long转换,把前缀(A/B/C)转成行维度 result = pd.wide_to_long( df_renamed, stubnames=['HH', 'JJ', 'KK'], # 目标列的前缀 i=['TT', 'YY', 'ZZ'], # 保留的索引列(不需要转换的列) j='group', # 临时生成的分组列(后面可以删掉) sep='_', # 列名的分隔符 suffix='.+' # 匹配列名的后缀 ).reset_index().drop('group', axis=1) # 重置索引并删除临时分组列
这个方法的优势是扩展性更强,比如如果以后新增D1/D2/D3列,只需要在重命名的时候加上对应映射即可。
两种方法都能高效实现你的需求,第一种更简洁直接,第二种更灵活,你可以根据实际情况选择~
内容的提问来源于stack exchange,提问作者zitoun
相关产品推荐
相关产品推荐

