如何在Pandas DataFrame中生成记录学生上次前三排名预测分数的新列
问题描述
现有一个按日期降序排列的DataFrame,记录学生班级排名(Rank)和预测分数(Predicted_Score),数据如下:
Date Student_ID Rank Predicted_Score 4/7/2021 33 2 87 13/6/2021 33 4 88 31/3/2021 33 7 88 28/2/2021 33 2 86 14/2/2021 33 10 86 31/1/2021 33 8 86 23/12/2020 33 1 81 8/11/2020 33 3 80 21/10/2020 33 3 80 23/9/2020 33 4 80 20/5/2020 33 3 80 29/4/2020 33 4 80 15/4/2020 33 2 79 26/2/2020 33 3 79 12/2/2020 33 5 79 29/1/2020 33 1 70
需要新增一列Recent_Predicted_Score,记录该学生上次进入班级前三(Rank为1、2、3)时的Predicted_Score,期望结果如下:
Date Student_ID Rank Predicted_Score Recent_Predicted_Score 4/7/2021 33 2 87 86 13/6/2021 33 4 88 86 31/3/2021 33 7 88 86 28/2/2021 33 2 86 81 14/2/2021 33 10 86 81 31/1/2021 33 8 86 81 23/12/2020 33 1 81 80 8/11/2020 33 3 80 80 21/10/2020 33 3 80 80 23/9/2020 33 4 80 80 20/5/2020 33 3 80 79 29/4/2020 33 4 80 79 15/4/2020 33 2 79 79 26/2/2020 33 3 79 70 12/2/2020 33 5 79 70 29/1/2020 33 1 70
尝试过以下代码但未成功:
df.sort_values(by = ['Student_ID', 'Date'], ascending = [True, False], inplace = True) lp1 = df['Predicted_Score'].where(df['Rank'].isin([1,2,3])).groupby(df['Student_ID']).bfill() lp2 = df.groupby(['Student_ID', 'Rank'])['Predicted_Score'].shift(-1) df = df.assign(Recent_Predicted_Score=lp1.mask(df['Rank'].isin([1,2,3]), lp2))
解决方案
核心思路:先标记所有前三记录的分数,再按日期降序获取每条记录的上一个前三分数,最后用向前填充补全非前三记录的空缺。
完整实现代码
# 确保数据按Student_ID和Date降序排列(原数据已满足可跳过) df.sort_values(by=['Student_ID', 'Date'], ascending=[True, False], inplace=True) # 1. 仅保留前三记录的Predicted_Score,其余设为NaN df['temp_score'] = df['Predicted_Score'].where(df['Rank'].isin([1,2,3])) # 2. 按学生分组,将前三分数向下偏移一位,得到每条记录的上一个前三分数 df['Recent_Predicted_Score'] = df.groupby('Student_ID')['temp_score'].shift(1) # 3. 向前填充,让非前三记录继承上一条的Recent_Predicted_Score df['Recent_Predicted_Score'] = df.groupby('Student_ID')['Recent_Predicted_Score'].ffill() # 4. 删除临时列 df.drop('temp_score', axis=1, inplace=True)
逻辑说明
- 步骤1:用
where筛选出前三记录的分数,其他记录标记为空白,方便后续定位有效数据 - 步骤2:
shift(1)将每个学生的前三分数向下移动一行,正好对应当前记录的上次前三分数 - 步骤3:
ffill()向前填充,解决非前三记录没有对应上次分数的问题,让它们延续上一条记录的结果 - 最终最早的记录(29/1/2020)因为没有更早的前三数据,
Recent_Predicted_Score会保持为空,符合示例要求
内容的提问来源于stack exchange,提问作者Apook
相关产品推荐
相关产品推荐

