如何将指定结构的Pandas DataFrame熔解转换为目标长表格式?
解决宽表转长表的Pandas操作
嘿,这个需求其实就是典型的宽格式DataFrame转长格式场景,我给你提供两种简洁的实现方法,你可以根据自己的习惯选择:
方法一:拆分后合并(直观易懂)
这种方法思路直接:把prod1和prod2对应的列分别提取出来,重命名成目标格式,再合并到一起,新手也能快速理解。
import pandas as pd # 原始数据 df = pd.DataFrame({'custid':[1,2,3,4], 'prod1':['jeans','tshirt','jacket','tshirt'], 'prod1_hnode1':[1,2,3,2], 'prod1_hnode2':[6,7,8,7], 'prod2':['tshirt','jeans','jacket','shirt'], 'prod2_hnode1':[2,1,3,4], 'prod2_hnode2':[7,6,8,7]}) # 处理prod1组:重命名列并添加prod标识 prod1_part = df[['custid', 'prod1', 'prod1_hnode1', 'prod1_hnode2']].rename( columns={'prod1': 'rec', 'prod1_hnode1': 'hnode1', 'prod1_hnode2': 'hnode2'} ) prod1_part['prod'] = 'prod1' # 处理prod2组:同样重命名列并添加prod标识 prod2_part = df[['custid', 'prod2', 'prod2_hnode1', 'prod2_hnode2']].rename( columns={'prod2': 'rec', 'prod2_hnode1': 'hnode1', 'prod2_hnode2': 'hnode2'} ) prod2_part['prod'] = 'prod2' # 合并两个部分并按custid排序 dfnew = pd.concat([prod1_part, prod2_part], ignore_index=True) dfnew = dfnew.sort_values('custid').reset_index(drop=True) # 调整列顺序和目标格式一致 dfnew = dfnew[['custid', 'prod', 'rec', 'hnode1', 'hnode2']] print(dfnew)
运行后得到的结果完全符合你的要求:
custid prod rec hnode1 hnode2 0 1 prod1 jeans 1 6 1 1 prod2 tshirt 2 7 2 2 prod1 tshirt 2 7 3 2 prod2 jeans 1 6 4 3 prod1 jacket 3 8 5 3 prod2 jacket 3 8 6 4 prod1 tshirt 2 7 7 4 prod2 shirt 4 7
方法二:使用pd.wide_to_long()(专业高效)
Pandas专门提供了wide_to_long()函数来处理这种带编号前缀的宽表转长表场景,代码更简洁,适合处理更复杂的多组列转换需求。
import pandas as pd # 原始数据 df = pd.DataFrame({'custid':[1,2,3,4], 'prod1':['jeans','tshirt','jacket','tshirt'], 'prod1_hnode1':[1,2,3,2], 'prod1_hnode2':[6,7,8,7], 'prod2':['tshirt','jeans','jacket','shirt'], 'prod2_hnode1':[2,1,3,4], 'prod2_hnode2':[7,6,8,7]}) # 先重命名列,让列名符合wide_to_long的格式:{字段名}_{prod编号} df_renamed = df.rename(columns={ 'prod1': 'rec_1', 'prod1_hnode1': 'hnode1_1', 'prod1_hnode2': 'hnode2_1', 'prod2': 'rec_2', 'prod2_hnode1': 'hnode1_2', 'prod2_hnode2': 'hnode2_2' }) # 使用wide_to_long转长表 dfnew = pd.wide_to_long( df_renamed, stubnames=['rec', 'hnode1', 'hnode2'], # 对应目标表的字段名 i='custid', # 标识符列(保留不变的列) j='prod_num', # 从列名中提取的prod编号 sep='_', # 列名中字段和编号的分隔符 suffix='\\d+' # 匹配编号的正则(这里匹配数字) ).reset_index() # 把prod_num转换成目标格式的prod1/prod2 dfnew['prod'] = 'prod' + dfnew['prod_num'].astype(str) # 调整列顺序并删除临时列 dfnew = dfnew[['custid', 'prod', 'rec', 'hnode1', 'hnode2']].drop('prod_num', axis=1) print(dfnew)
这个方法的结果和方法一完全一致,处理大规模数据时效率更高。
内容的提问来源于stack exchange,提问作者tushaR
相关产品推荐
相关产品推荐

