Python pandas根据eperf2/mperf2/sperf2列值新增对应TestDate行
需求说明
- 基于pandas DataFrame中
eperf2、mperf2、sperf2三列的有效值生成TestDate字段,StudentTestID为学生唯一标识,规则如下:- 若某
StudentTestID对应的eperf2列存在非空有效值,该条记录的TestDate字段赋值为"April 1" - 若同一
StudentTestID对应的mperf2列存在非空有效值,在DataFrame中新增一行,该行StudentTestID与原记录保持一致,TestDate字段赋值为"May 1" - 若同一
StudentTestID对应的sperf2列存在非空有效值,在DataFrame中再新增一行,该行StudentTestID与原记录保持一致,TestDate字段赋值为"June 1"
- 若某
- 每个
StudentTestID最多生成3条对应不同TestDate的记录;若对应绩效列无有效值,无需新增行或为该ID赋值TestDate。
实现方案
不需要写逐行循环逻辑,用pandas的批量处理方法即可高效实现,在你现有预处理代码后追加以下代码即可:
import numpy as np # 1. 预处理:将绩效列中的空字符串、全空格内容统一替换为NaN,避免误判有效值 perf_columns = ['eperf2', 'mperf2', 'sperf2'] df[perf_columns] = df[perf_columns].replace(r'^\s*$', np.nan, regex=True) # 2. 处理原记录的4月TestDate赋值(匹配eperf2有效场景) df['TestDate'] = np.where(df['eperf2'].notna(), 'April 1', np.nan) # 3. 构造需要新增的5月记录:筛选mperf2非空的行,复制后修改TestDate may_records = df[df['mperf2'].notna()].copy() may_records['TestDate'] = 'May 1' # 4. 构造需要新增的6月记录:筛选sperf2非空的行,复制后修改TestDate june_records = df[df['sperf2'].notna()].copy() june_records['TestDate'] = 'June 1' # 5. 拼接原表和新增行,重置索引得到最终结果 final_df = pd.concat([df, may_records, june_records], ignore_index=True) # 可选:如果需要剔除三列绩效全空、无有效TestDate的记录,取消注释下一行即可 # final_df = final_df[final_df['TestDate'].notna()].reset_index(drop=True)
补充说明
- 该实现完全匹配规则要求:
eperf2有效时仅修改原记录的TestDate不新增行,mperf2/sperf2有效时才新增对应日期的行,单个学生最多生成3条记录 - 批量处理的性能远高于逐行遍历,即使是十万级数据量也能快速运行
- 从你提供的样例数据看,三列绩效字段存在大量空字符串(比如最后一行三列全空、部分行sperf2为空白),预处理步骤可以准确识别这类无效值,不会错误生成多余行
- 如果需要给不同TestDate的记录匹配对应绩效值到分数字段,可以在构造对应月份记录时直接赋值,例如给5月记录赋值分数:
may_records['ScoreLabel'] = may_records['mperf2']
注意:如果业务要求不同TestDate的记录仅保留对应月份的绩效值、清空其他月份绩效字段,可以在构造新增行时按需处理,例如给5月记录清空其他绩效字段:
may_records[['eperf2', 'sperf2']] = np.nan,根据实际字段要求调整即可。
内容的提问来源于stack exchange,提问作者Marc Williams
相关产品推荐
相关产品推荐

