pandas如何堆叠多列数据并按原始来源列生成对应匹配字段
问题原因
原代码存在两个核心错误:
- 实现逻辑偏差:
np.select仅能在原宽表的单行维度赋值,而需求本质是宽表转长表——每个TestID对应3条不同科目的记录,宽表单行仅能存储1个TestDate值,无法承载三个科目的不同考试日期。 - 判断条件失效:数据集中ELA/Math/Science列存储的是W/P/NI/A类成绩值,所有行的ELA列均不等于字符串
'[]',np.select按顺序优先命中第一个满足的条件,因此所有行都被赋值为第一个匹配值April 1。
可行解决方案
pandas内置的melt方法专门用于这类列堆叠的宽长表转换场景,无需手动编写多条件判断,实现步骤:
- 调用
melt保留无需拆分的TestID列,将三个科目列堆叠为两列:原科目列名存入TestName字段,对应成绩值存入Score字段 - 构建科目与考试日期的映射字典,通过字段映射快速生成
TestDate列 - 调整列顺序、按需排序,匹配预期输出格式
完整实现代码:
import pandas as pd # 完成成绩列堆叠,宽表转长表 df_long = df.melt( id_vars="TestID", value_vars=["ELA", "Math", "Science"], var_name="TestName", value_name="Score" ) # 批量匹配对应考试日期 date_map = {"ELA": "April 1", "Math": "May 1", "Science": "June 1"} df_long["TestDate"] = df_long["TestName"].map(date_map) # 按TestID、科目排序,调整列顺序 df_long = df_long.sort_values( by=["TestID", "TestName"], ignore_index=True )[["TestID", "TestName", "TestDate", "Score"]]
运行后输出结果与预期完全一致,前6行示例:
TestID TestName TestDate Score 0 1005327 ELA April 1 P 1 1005327 Math May 1 P 2 1005327 Science June 1 P 3 1020285 ELA April 1 NI 4 1020285 Math May 1 P 5 1020285 Science June 1 W
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

