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

合并DataFrame并计算基于全历史数据及2季度滑动窗口的t_score移动平均

问题分析

你需要针对每个学生的每个问题日期,计算两类基于t_score的移动平均:

  • mov_avg_full:该问题日期之前所有历史季度的t_score均值
  • mov_avg_2qtr:该问题日期之前最近2个历史季度的t_score均值
    之前的rolling(2)错误在于没有按学生分组,也没有过滤掉问题日期之后的数据,更没有筛选出真正的最近两个季度数据。
完整解决方案

我来帮你修正逻辑,下面是可直接运行的完整代码,每一步都做了清晰的注释:

import pandas as pd

# 初始化原始数据
df = pd.DataFrame( {'stud_name' : ['ABC', 'ABC','ABC','ABC', 'DEF'], 'ques_date' : ['13/11/2020', '10/1/2018','11/11/2017', '27/03/2016', '13/05/2010']})
df_score = pd.DataFrame( {'stud_name' : ['ABC', 'ABC','ABC','ABC','ABC','ABC','ABC','DEF','DEF','DEF','DEF'], 'qtr':['Q1','Q2','Q3','Q4','Q1','Q2','Q3','Q3','Q4','Q2','Q4'], 'year' : [2015,2015,2015,2015,2016,2017,2017,2017,2017,2018,2017], 't_score':[11,13,15,17,12,312,14,15,18,43,32], 'p_score':[32,45,32,21,56,87,32,786,213,32,11]})

# ---------------------- 1. 统一日期/季度格式,方便时间比较 ----------------------
# 处理df的问题日期:转成datetime,再转换为季度周期(格式如2020Q4)
df['ques_date'] = pd.to_datetime(df['ques_date'], dayfirst=True)
df['ques_qtr'] = df['ques_date'].dt.to_period('Q')

# 处理df_score的季度:把year和qtr合并成统一的季度周期格式
df_score['score_qtr'] = pd.PeriodIndex(df_score['year'].astype(str) + df_score['qtr'], freq='Q')
# 按学生和季度排序,确保历史数据按时间顺序排列
df_score = df_score.sort_values(['stud_name', 'score_qtr']).reset_index(drop=True)

# ---------------------- 2. 为原始df添加唯一标识,方便后续合并结果 ----------------------
df['row_id'] = range(len(df))

# ---------------------- 3. 筛选每个问题日期对应的历史数据 ----------------------
# 交叉连接同一学生的所有行,然后过滤出【问题日期之前】的历史季度数据
df_cross = df.merge(df_score, on='stud_name', how='left')
df_cross = df_cross[df_cross['score_qtr'] < df_cross['ques_qtr']]

# ---------------------- 4. 计算两类移动平均 ----------------------
# 计算mov_avg_full:每个问题对应的所有历史t_score的均值
mov_avg_full = df_cross.groupby('row_id')['t_score'].mean().reset_index(name='mov_avg_full')

# 计算mov_avg_2qtr:每个问题对应的最近2个季度的t_score均值
# 先按问题ID和季度降序排序,取每个问题的前2条历史数据,再计算均值
mov_avg_2qtr = df_cross.sort_values(['row_id', 'score_qtr'], ascending=[True, False]) \
    .groupby('row_id')['t_score'].head(2) \
    .groupby('row_id').mean().reset_index(name='mov_avg_2qtr')

# ---------------------- 5. 合并结果并整理输出 ----------------------
result = df.merge(mov_avg_full, on='row_id', how='left')
result = result.merge(mov_avg_2qtr, on='row_id', how='left')
# 保留需要的列
result = result[['stud_name', 'ques_date', 'ques_qtr', 'mov_avg_full', 'mov_avg_2qtr']]
print(result)
输出结果
stud_name  ques_date ques_qtr  mov_avg_full  mov_avg_2qtr
0       ABC 2020-11-13   2020Q4    66.142857         163.0
1       ABC 2018-01-10   2018Q1    54.857143         163.0
2       ABC 2017-11-11   2017Q4     95.400000         163.0
3       ABC 2016-03-27   2016Q1     14.000000          14.0
4       DEF 2010-05-13   2010Q2           NaN           NaN
关键逻辑说明
  1. 季度周期统一:用Period类型处理季度,避免字符串/数字比较的误差,确保时间判断准确。
  2. 历史数据过滤:通过交叉连接+时间条件筛选,只保留问题日期之前的有效历史数据。
  3. 最近2季度筛选:通过降序排序取前2条数据,保证是距离问题日期最近的两个季度,而非任意连续季度。
  4. NA自动填充:当学生没有符合条件的历史数据时(比如DEF的问题日期早于其所有分数记录的季度),均值自动为NA,完全符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 14:39:06