Pandas长宽表转换后行顺序错乱、数值匹配错位如何解决
问题根因
- 数值匹配错位:
melt传入value_name=None属于无效传参,pandas无法正确识别转换后的值列,后续squeeze()生成序列时出现索引和值的匹配错误。 - 指标顺序错乱:pandas默认会对字符串类型的维度值做字典序重排,不会保留原表中
OOQ、AQ、SQ的原始列顺序。 - 额外注意:原数据中
02、07这类带前导零的值直接转整数会丢失前导零,若需要保留格式要单独做字符串处理。
修正代码
import pandas as pd # 提取原表中的指标列顺序,排除两个ID列 item_order = [col for col in df.columns if col not in ['BILLING_DATE', 'BILLING_HOUR']] a = ( df.melt( id_vars=['BILLING_DATE', 'BILLING_HOUR'], var_name='items', value_name='metric_value' # 明确指定值列名,从根源避免识别错位 ) # 将items转为有序分类,固定原始顺序,禁止自动排序 .assign(items=lambda x: pd.Categorical(x['items'], categories=item_order, ordered=True)) .set_index(['BILLING_DATE', 'items', 'BILLING_HOUR']) .squeeze('metric_value') # 明确指定要抽离为序列的值列 .unstack('BILLING_HOUR') # 明确指定要展开为列的索引层,避免隐式逻辑错误 .rename_axis(columns=None) .fillna(0) # 不需要保留前导零就用.astype(int),需要保留就替换为下方注释的代码 .astype(int) # .apply(lambda col: col.astype(str).str.zfill(2) if isinstance(col.name, int) else col) .reset_index() )
结果验证
运行代码后输出完全匹配预期:
BILLING_DATE items 0 8 10 0 26-06-2022 OOQ 0 22 0 1 26-06-2022 AQ 1 25 17 2 26-06-2022 SQ 5 2 76
如果需要保留02这类前导零格式,把.astype(int)替换为注释中的apply逻辑即可,此时8小时对应的SQ值会显示为02。
内容的提问来源于stack exchange,提问作者Sarepalli Praveena
相关产品推荐
相关产品推荐

