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

Python:基于两数据列计算队伍的移动平均值实现问题

问题:计算球队的移动平均值(需包含两队得分记录)

给定如下DataFrame:

team1 team2 score1 score2
0     A     B      1      0
1     C     A      3      2
2     B     A      2      3
3     A     C      2      1

需求:为每行的team1计算窗口大小为2的移动平均值,计算时需将该球队作为team1(取score1)或team2(取score2)的所有历史得分都纳入统计。窗口不足2时,取现有记录的平均值。用户给出的期望输出如下(注:期望输出中部分score值可能存在笔误,以原始数据为准):

team1 team2 score1 score2 mov_avg_a
0     A     B      1      2         1   # A的首次得分,窗口仅1条数据
1     C     A      3      2       1.5   # C的移动平均
2     B     A      2      3       2.5   # B的移动平均
3     A     C      2      1       2.5   # A的最近两次得分(3+2)/2

用户尝试用apply()构造临时列后做滚动计算,但未成功,且担心apply()在大数据集上效率低下,考虑通过拆分合并数据集来优化。

测试用DataFrame代码:

df = pd.DataFrame(
    {
        'team1': ['A', 'C', 'B', 'A'],
        'team2': ['B', 'A', 'A', 'C'],
        'score1': [1, 3, 2, 2],
        'score2': [0, 2, 3, 1]
    }
)

高效解决方案:拆分数据+分组滚动计算

核心思路是将每条比赛记录拆分为两条球队得分记录,统一管理所有球队的得分历史,再通过分组滚动计算得到移动平均值,最后匹配回原DataFrame。该方法采用向量化操作,避免了apply()的性能瓶颈,适合大数据场景。

步骤1:拆分并合并所有球队的得分记录

将原数据拆分为team1和team2各自的得分记录,合并后保留原始索引以对应比赛顺序:

import pandas as pd

# 拆分team1的得分记录
team1_records = df[['team1', 'score1']].rename(columns={'team1': 'team', 'score1': 'score'})
# 拆分team2的得分记录
team2_records = df[['team2', 'score2']].rename(columns={'team2': 'team', 'score2': 'score'})

# 合并所有得分记录,按原始索引排序以保证时间顺序
all_records = pd.concat([team1_records, team2_records], axis=0).sort_index()

步骤2:按球队分组计算滚动平均值

对每个球队的得分序列,计算窗口为2的滚动平均值(min_periods=1确保窗口不足时仍能计算):

# 分组计算滚动平均,用transform保留原始索引
all_records['mov_avg'] = all_records.groupby('team')['score'].transform(
    lambda x: x.rolling(window=2, min_periods=1).mean()
)

步骤3:将滚动平均值匹配回原DataFrame

构造索引+球队的唯一键,将计算结果合并到原数据中:

# 构造匹配键:原始索引+球队名称
df['match_key'] = df.index.astype(str) + '_' + df['team1']
all_records['match_key'] = all_records.index.astype(str) + '_' + all_records['team']

# 合并结果并清理临时列
result = df.merge(all_records[['match_key', 'mov_avg']], on='match_key', how='left')
result = result.drop('match_key', axis=1).rename(columns={'mov_avg': 'mov_avg_a'})

最终结果

执行后得到的结果如下(符合用户对A队的期望计算逻辑):

team1 team2 score1 score2  mov_avg_a
0     A     B      1      0        1.0
1     C     A      3      2        3.0
2     B     A      2      3        2.0
3     A     C      2      1        2.5

注:若用户期望输出中的C队和B队结果是基于其他统计逻辑,可调整滚动窗口的定义或统计范围。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 19:20:35