You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas实战:学生成绩重评后捕获更新列名至指定单列

问题描述

现有学生成绩重评前、后两个数据集,合并后需新增anyimprovement和improvedfield两列。目前anyimprovement列已完成(用于标记记录是否有改进、是否为新条目),但需要完善improvedfield列的实现逻辑:

  • 同一主键(name、class、exam)的记录,将重评后发生变化的列名(如科目成绩、result等)用逗号分隔存入该列;
  • 无改进时标记为“no improvement”;
  • 新条目标记为“new entry”。

当前使用的代码如下:

# 拼接name、class、exam生成主键列,拼接maths、physics、chemistry生成次键列
concatdf['PrimaryKey'] = concatdf['name'] + '_' + concatdf['class'] + '_' + concatdf['exam']
concatdf['SecondaryKey'] = concatdf['maths'].astype(str) + '_' + concatdf['physics'].astype(str) + '_' + concatdf['chemistry'].astype(str)

dupedf = concatdf.loc[concatdf.duplicated(subset=['PrimaryKey', 'SecondaryKey'],keep=False)]
dupedf1 = concatdf.loc[concatdf.duplicated(subset=['PrimaryKey'],keep=False)]

for i,j in dupedf.iterrows():
    for k,l in dupedf1.iterrows():
        if l['PrimaryKey'] == j['PrimaryKey']:
            dupedf = dupedf.drop_duplicates(subset=['PrimaryKey','SecondaryKey'],keep='last')
            dupedf['any improvement'] = 'No'
            # dupedf['improved subject'] = ' '
        else:
            dupedf1 = dupedf1.drop_duplicates(subset=['SecondaryKey'],keep=False)
            dupedf1 = dupedf1.drop_duplicates(subset=['PrimaryKey'],keep='last')
            dupedf1['any improvement'] = 'Yes'
           # dupedf1['improved subject'] = 'column name'
解决方案

思路说明

原代码用双重循环处理重复数据,效率低且逻辑混乱。推荐按主键分组对比的方式,步骤如下:

  1. 给重评前、后的数据添加版本标识,方便区分新旧记录;
  2. 按主键PrimaryKey分组,判断每组记录数量:1条则为新条目,2条则对比字段差异;
  3. 根据对比结果填充anyimprovement和improvedfield列。

实现代码

首先处理数据合并与标识添加:

import pandas as pd

# 假设重评前数据为df_pre,重评后为df_post
df_pre['version'] = 'pre'  # 标记重评前数据
df_post['version'] = 'post'  # 标记重评后数据
concatdf = pd.concat([df_pre, df_post], ignore_index=True)

# 生成主键列
concatdf['PrimaryKey'] = concatdf['name'] + '_' + concatdf['class'] + '_' + concatdf['exam']

# 初始化目标列
concatdf['anyimprovement'] = ''
concatdf['improvedfield'] = ''

然后分组处理差异:

# 定义需要对比的字段(根据实际需求调整)
compare_columns = ['maths', 'physics', 'chemistry', 'result']

# 按主键分组遍历
for pk, group in concatdf.groupby('PrimaryKey'):
    if len(group) == 1:
        # 分组仅一条记录,判定为新条目
        concatdf.loc[concatdf['PrimaryKey'] == pk, ['anyimprovement', 'improvedfield']] = 'new entry'
    else:
        # 获取重评前后的单条记录
        pre_record = group[group['version'] == 'pre'].iloc[0]
        post_record = group[group['version'] == 'post'].iloc[0]
        
        # 筛选出有变化的字段
        changed_fields = [col for col in compare_columns if pre_record[col] != post_record[col]]
        
        if not changed_fields:
            # 无字段变化
            concatdf.loc[concatdf['PrimaryKey'] == pk, 'anyimprovement'] = 'No'
            concatdf.loc[concatdf['PrimaryKey'] == pk, 'improvedfield'] = 'no improvement'
        else:
            # 有字段变化
            concatdf.loc[concatdf['PrimaryKey'] == pk, 'anyimprovement'] = 'Yes'
            concatdf.loc[concatdf['PrimaryKey'] == pk, 'improvedfield'] = ', '.join(changed_fields)

关键说明

  • 版本标识是核心:如果合并时没有区分重评前后,可通过数据来源(比如原数据集的顺序)补充这个标识;
  • 对比字段可自定义:compare_columns列表根据实际需要调整,比如加入其他科目或评价字段;
  • 避免双重循环:用groupby分组处理比原代码的双重循环效率高得多,尤其当数据量较大时。

内容的提问来源于stack exchange,提问作者Beginner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 08:57:48