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

如何计算DataFrame双ID列中各ID的上月滚动平均值?

问题描述

我参考了Stack Overflow上的一个Pandas分组滚动平均问题,但我的数据有差异:包含ID 1和ID 2两个ID列(日期格式为dd/mm/yyyy)。

需求是:计算每个特定ID过去一个月的平均得分。比如计算ID 1000的上月平均评分时,要汇总它在ID 1或ID 2列中出现的所有相关得分,且数据集每一行需对应显示ID 1和ID 2的过去30天平均得分。

我尝试了以下代码:

dataset['Date'] = pandas.to_datetime(dataset['Date'])
dataset = dataset.sort_values(by=['ID 1','Date'])
dataset['ID 1 last month average rating'] = dataset.set_index('Date').groupby('ID 1', 
sort=False)['ID 1 Score'].rolling('30D', closed='left').mean().round(2).to_numpy()
dataset['ID 2 last month average rating'] = dataset.set_index('Date').groupby('ID 2', 
sort=False)['ID 2 Score'].rolling('30D', closed='left').mean().round(2).to_numpy()

但结果不正确,请问哪里出错了?

更新说明:已更新输入数据,期望输出如下(新增ID1 30D avg rtg和ID2 30D avg rtg两列,以ID1000为例,需汇总它在ID1、ID2列中的历史得分计算截至对应日期的过去30天平均值):

DateID 1ID 2ID 1 ScoreID 2 ScoreID1 30D avg rtgID2 30D avg rtg
16/7/2022100110000.895.354.045
10/7/202210009013.422.674.67
8/7/202253010001.524.67

能否为所有ID实现这样的输出?


问题分析与解决方案

错误原因

你的代码存在两个核心问题:

  1. 得分拆分统计:仅单独计算ID 1对应ID 1 Score、ID 2对应ID 2 Score的滚动平均,没有把同一个ID在两列中出现的所有得分合并计算,不符合“汇总同一ID全量得分”的需求。
  2. 排序逻辑错误:仅按ID 1+Date排序,未全局按日期排序,导致滚动窗口的时间范围计算偏差。

解决思路

先将原数据拆分为统一的「ID-日期-得分」格式,把同一个ID在两列中的得分合并,再计算每个ID的30天滚动平均,最后将结果映射回原数据集的每一行。

完整代码

import pandas as pd

# 1. 处理日期格式,全局按日期排序(dayfirst=True适配dd/mm/yyyy格式)
dataset['Date'] = pd.to_datetime(dataset['Date'], dayfirst=True)
dataset = dataset.sort_values(by='Date').reset_index(drop=True)

# 2. 构建全量ID得分表:合并ID1和ID2的得分记录
id1_records = dataset[['Date', 'ID 1', 'ID 1 Score']].rename(columns={'ID 1': 'ID', 'ID 1 Score': 'Score'})
id2_records = dataset[['Date', 'ID 2', 'ID 2 Score']].rename(columns={'ID 2': 'ID', 'ID 2 Score': 'Score'})
all_id_records = pd.concat([id1_records, id2_records], ignore_index=True)

# 3. 计算每个ID的30天滚动平均(closed='left'表示排除当前日期的得分)
all_id_records = all_id_records.sort_values(by=['ID', 'Date'])
rolling_avg_results = all_id_records.set_index('Date').groupby('ID', sort=False)['Score']\
                                   .rolling('30D', closed='left').mean().reset_index()
rolling_avg_results.rename(columns={'Score': '30D_avg_rtg'}, inplace=True)

# 4. 将滚动平均映射回原数据集
# 匹配ID1对应的30天平均得分
dataset = dataset.merge(rolling_avg_results, left_on=['Date', 'ID 1'], right_on=['Date', 'ID'], how='left')
dataset.rename(columns={'30D_avg_rtg': 'ID1 30D avg rtg'}, inplace=True)
dataset.drop('ID', axis=1, inplace=True)

# 匹配ID2对应的30天平均得分
dataset = dataset.merge(rolling_avg_results, left_on=['Date', 'ID 2'], right_on=['Date', 'ID'], how='left')
dataset.rename(columns={'30D_avg_rtg': 'ID2 30D avg rtg'}, inplace=True)
dataset.drop('ID', axis=1, inplace=True)

# 按示例格式保留三位小数(可选)
dataset['ID1 30D avg rtg'] = dataset['ID1 30D avg rtg'].round(3)
dataset['ID2 30D avg rtg'] = dataset['ID2 30D avg rtg'].round(3)

结果验证

用你提供的示例数据运行代码后,会得到与期望一致的输出:

  • 16/7/2022行的ID2 30D avg rtg为4.045,是ID1000在8/7的4.67和10/7的3.42的平均值;
  • 10/7/2022行的ID1 30D avg rtg为4.67,是ID1000在8/7的唯一得分。

内容的提问来源于Stack Exchange,提问作者Iason

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 03:15:09