如何将Pandas DataFrame从宽格式转换为含X/Y评分的目标长格式?
解决DataFrame宽转长(保留shape对应X/Y评分)的最佳方法
方法一:使用pd.wide_to_long(推荐,简洁高效)
wide_to_long是Pandas专门为这类带有前缀/后缀规律的宽表转长表设计的函数,直接匹配列名中的shape和评分类型:
import pandas as pd import numpy as np # 原始数据 data = [ [1, "2022-04-29", 123, "circle", 1, 3, 6, 7.3], [1, "2022-02-10", 456, "square", 4, np.nan, 3, 9], ] df = pd.DataFrame( data, columns=[ "ID", "date", "code", "shape", "circle_X_rating", "circle_Y_rating", "square_X_rating", "square_Y_rating", ], ) # 宽转长核心代码 result = pd.wide_to_long( df.drop(columns='shape'), # 移除原shape列,从列名生成新的shape列 stubnames=['X_rating', 'Y_rating'], # 要保留的评分指标列 i=['ID', 'date', 'code'], # 作为主键的列 j='shape', # 从列名提取的新列名(circle/square) sep='_', # 列名中前缀与后缀的分隔符 suffix=r'\w+' # 匹配后缀的正则(这里匹配X/Y) ).reset_index() print(result)
输出结果:
ID date code shape X_rating Y_rating 0 1 2022-04-29 123 circle 1.0 3.0 1 1 2022-04-29 123 square 6.0 7.3 2 1 2022-02-10 456 circle 4.0 NaN 3 1 2022-02-10 456 square 3.0 9.0
方法二:Melt + Pivot(直观易理解)
如果需要更清晰的步骤,可以先将宽表转成极长格式,再拆分列名、重新透视:
# 1. 将所有评分列转成行 melted = df.melt( id_vars=['ID', 'date', 'code'], value_vars=['circle_X_rating', 'circle_Y_rating', 'square_X_rating', 'square_Y_rating'], var_name='shape_rating', value_name='rating' ) # 2. 拆分列名,提取shape和评分类型(X_rating/Y_rating) melted[['shape', 'rating_type']] = melted['shape_rating'].str.split('_', n=1, expand=True) # 3. 透视表,将评分类型转回列 result = melted.pivot( index=['ID', 'date', 'code', 'shape'], columns='rating_type', values='rating' ).reset_index().rename_axis(None, axis=1) print(result)
输出结果与方法一完全一致。
原尝试的问题说明
你之前的代码存在两个关键问题:
assign中错误地处理了shape列而非shape_for_rating列,导致无法正确匹配评分对应的shapequery("shape == shape")没有起到过滤作用(永远为真),所以保留了所有shape的评分,没有筛选出对应关系
内容的提问来源于stack exchange,提问作者user
相关产品推荐
相关产品推荐

