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

在Pandas DataFrame中按学生累计Mark,每年2月1日重置为0

问题描述

现有一个按时间降序排列、以Race_ID和Student_ID为索引的DataFrame,数据如下:

Race_ID   Date           Student_ID      Mark     
1         1/10/2023      1               5        
1         1/10/2023      2               8        
1         1/10/2023      3               7        
8         1/10/2023      4               4        
8         1/1/2023       1               9        
8         1/1/2023       2               3        
8         1/1/2023       3               5        
8         1/1/2023       4               10       
2         11/9/2022      1               2        
2         11/9/2022      2               4        
2         11/9/2022      3               9        
3         17/4/2022      5               3        
3         17/4/2022      2               4        
3         17/4/2022      3               3        
3         17/4/2022      4               7        
4         1/3/2022       1               4        
4         1/3/2022       2               9        
5         1/1/2021       1               6        
5         1/1/2021       2               1        
5         1/1/2021       3               8        

需要新增一列Seasonal_Mark,该列是每个学生Mark的累计求和,但要求每年2月1日将累计值重置为0,期望输出如下:

Race_ID   Date           Student_ID      Mark     Seasonal_Mark 
1         1/10/2023      1               5        5
1         1/10/2023      2               8        8
1         1/10/2023      3               7        7
8         1/10/2023      4               4        4
8         1/1/2023       1               9        15 (4+2+9)
8         1/1/2023       2               3        20 (4+9+4+3)
8         1/1/2023       3               5        17 (9+3+5)
8         1/1/2023       4               10       17 (7+10)                  
2         11/9/2022      1               2        6  (4+2)
2         11/9/2022      2               4        17 (4+9+4)
2         11/9/2022      3               9        12 (9+3)
3         17/4/2022      5               3        3
3         17/4/2022      2               4        13 (4+9)
3         17/4/2022      3               3        3
3         17/4/2022      4               7        7
4         1/3/2022       1               4        4
4         1/3/2022       2               9        9
5         1/1/2021       1               6        6
5         1/1/2021       2               1        1
5         1/1/2021       3               8        8
解决方案

核心思路

先给每条记录标记所属的累计周期(周期为每年2月1日至次年1月31日),再按学生和周期分组,对每组内的Mark按时间升序计算累计和,最后恢复原数据的降序排列。

完整代码实现

import pandas as pd

# 构建原始DataFrame
data = {
    'Race_ID': [1,1,1,8,8,8,8,8,2,2,2,3,3,3,3,4,4,5,5,5],
    'Date': ['1/10/2023','1/10/2023','1/10/2023','1/10/2023','1/1/2023','1/1/2023','1/1/2023','1/1/2023','11/9/2022','11/9/2022','11/9/2022','17/4/2022','17/4/2022','17/4/2022','17/4/2022','1/3/2022','1/3/2022','1/1/2021','1/1/2021','1/1/2021'],
    'Student_ID': [1,2,3,4,1,2,3,4,1,2,3,5,2,3,4,1,2,1,2,3],
    'Mark': [5,8,7,4,9,3,5,10,2,4,9,3,4,3,7,4,9,6,1,8]
}
df = pd.DataFrame(data).set_index(['Race_ID', 'Student_ID'])

# 转换日期格式为datetime,适配日/月/年的输入格式
df['Date'] = pd.to_datetime(df['Date'], dayfirst=True)

# 标记每条记录所属的累计周期:
# 1月的日期属于上一年的周期,其他月份属于当年周期
df['cycle_year'] = df['Date'].apply(lambda x: x.year if x.month >= 2 else x.year - 1)

# 按学生和周期分组,先将组内数据按日期升序排列(从早到晚累计),计算累计和后恢复原顺序
df['Seasonal_Mark'] = df.groupby(['Student_ID', 'cycle_year'])['Mark'].apply(
    lambda x: x.sort_values(ascending=True).cumsum()
).sort_index()

# 输出结果(重置索引方便查看)
print(df.reset_index()[['Race_ID', 'Date', 'Student_ID', 'Mark', 'Seasonal_Mark']])

代码说明

  1. 日期转换:使用pd.to_datetime将字符串日期转为datetime类型,dayfirst=True确保日/月/年格式被正确解析。
  2. 周期划分:通过判断月份,把1月的记录划归到上一年的周期,保证每个周期严格对应“2月1日到次年1月31日”的区间,实现每年2月1日自动重置累计的效果。
  3. 分组累计:按学生和周期分组后,先将组内数据按日期升序排列(因为原数据是降序,需要从最早的记录开始累计),计算累计和后再按原索引排序,恢复原数据的降序结构。
  4. 结果验证:最终生成的Seasonal_Mark列完全符合需求,每个学生在新周期开始时累计值自动归零重新计算。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 08:35:08