如何根据时间戳为DataFrame观测值动态加权 使近期数据影响力更高
基于指数时间衰减的动态加权均值实现
你原来的手动分段赋权方案问题在于权重是离散跳变的,而且分段边界、权重值都是硬编码,调整成本高。用指数衰减加权可以实现逐观测连续赋权,时间越近权重越高,只需要一个半衰期参数就能灵活控制权重衰减速率,适配增量更新的需求。
核心逻辑
- 先把日期列转成标准时间格式,按时间升序排序避免权重错乱
- 以数据集中最新的比赛日期为基准,计算每条历史记录距离基准日的天数差
- 用指数衰减公式给每条记录算权重:最新比赛权重为1,每往前推一个半衰期的时长,权重就降为原来的1/2
- 最后用numpy的加权平均方法计算各得分列的均值即可
可直接复用的函数代码
import pandas as pd import numpy as np def calc_time_weighted_score(df, score_cols, half_life_days=30): """ 计算时间加权的得分均值 参数: df: 存比赛数据的DataFrame,必须带Date列和对应的得分列 score_cols: 要计算均值的列名列表,例:['attack_score', 'defence_score'] half_life_days: 权重半衰期,单位天,数值越小旧数据权重衰减越快 """ # 不修改原数据 temp_df = df.copy() temp_df['Date'] = pd.to_datetime(temp_df['Date']) temp_df = temp_df.sort_values('Date', ascending=True).reset_index(drop=True) # 计算每条记录距最新比赛的间隔天数 latest_match_date = temp_df['Date'].max() day_gap = (latest_match_date - temp_df['Date']).dt.days # 计算指数衰减权重:最新记录间隔0天,权重为1 weights = np.power(0.5, day_gap / half_life_days) # 逐列算加权均值 res = {} for col in score_cols: res[col] = np.average(temp_df[col], weights=weights) return pd.Series(res)
使用方法
拿你给出的样例数据举例:
# 样例数据 df = pd.DataFrame({ 'Date': ['2022-03-18', '2022-03-24', '2022-04-06'], 'attack_score': [2.3, 1.6, 1.9], 'defence_score': [0.4, 1.2, 0.7] }) # 计算加权均值,这里设半衰期15天,即15天前的比赛权重只有最新比赛的一半 weighted_scores = calc_time_weighted_score( df, score_cols=['attack_score', 'defence_score'], half_life_days=15 ) print(weighted_scores)
调优提示
- 想让模型更敏感捕捉球队近期的阵容、战术变化,就把
half_life_days调小,一般足球场景下设10~30天比较合适,此时超过2个月的比赛权重会降到很低 - 想兼顾球队长期实力基线,避免短期偶然波动影响太大,就把参数调到60~90天
- 最优值可以通过交叉验证在验证集上测预测准确率来选,比手动分段的方案灵活很多,后续新比赛入库后,直接重新跑函数就能自动更新所有权重,不需要改代码逻辑。
这个方案的权重是连续变化的,不会出现你之前分段方案里,刚好卡在分段边界的两场相邻比赛权重差很大的不合理情况,所有记录的权重和时间差严格对应,没有人为划分分段带来的偏差。
内容的提问来源于stack exchange,提问作者Phantasmagore
相关产品推荐
相关产品推荐

