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

优化Pandas groupby操作 高效计算多时间周期分组均值指标

解决方案

直接通过单轮分组+分组内时间筛选的方式完成所有周期的均值计算,全程无冗余数据生成,也无需循环创建/合并DataFrame:

实现代码

import pandas as pd
import numpy as np

# 原始数据生成逻辑
names = ['PersonA', 'PersonB', 'PersonC', 'PersonD','PersonE','PersonF']
team = ['Team1','Team2']
dates = pd.date_range(start = '2020-05-28', end = '2021-11-22')
df = pd.DataFrame({'runtime': np.repeat(dates, len(names)*len(team))})
df['name'] = len(dates)*len(team)*names
df['team'] = len(dates)*len(names)*team
df['A'] = 40 + 20*np.random.random(len(df))
df['B'] = .1 * np.random.random(len(df))
df['C'] = 1 +.5 * np.random.random(len(df))

# 计算逻辑开始
# 1. 预处理:按分组+时间排序,保证时间顺序正确
df_sorted = df.sort_values(['name', 'team', 'runtime']).copy()

# 2. 自定义周期和列后缀映射,后续加新周期直接修改这里即可
period_map = {
    '7D': 'w',   # 最近7天(周)
    '30D': 'm',  # 最近30天(月)
    '365D': 'y', # 最近365天(年)
    'all': 'at'  # 全时段
}
# 要计算均值的字段
calc_cols = ['A', 'B', 'C']

# 3. 定义分组内计算函数
def calc_period_means(gdf):
    res = {}
    # 取当前分组的最大时间作为截止时间
    max_dt = gdf['runtime'].max()
    for period, suffix in period_map.items():
        # 筛选对应周期的数据
        if period == 'all':
            period_df = gdf
        else:
            period_df = gdf[gdf['runtime'] >= max_dt - pd.Timedelta(period)]
        # 批量计算三个字段的均值
        col_means = period_df[calc_cols].mean()
        for col in calc_cols:
            res[f'{col}_{suffix}'] = col_means[col]
    return pd.Series(res)

# 4. 分组计算直接得到目标结构
result = df_sorted.groupby(['name', 'team'], as_index=False).apply(calc_period_means)

适配调整说明

  • 如果需要使用自然月/自然年而非固定天数计算,把pd.Timedelta(period)替换为pd.DateOffset(months=1)/pd.DateOffset(years=1)即可,自动适配闰月、闰年逻辑
  • 新增计算周期仅需在period_map中添加键值对,无需修改其他逻辑

方案优势

  • 仅执行1次分组操作,无循环创建DataFrame、合并的额外开销
  • 最终输出行数等于人数*队伍数,也就是当前场景下的12行,完全没有冗余数据,无论时间跨度多大都不会出现数据膨胀
  • 输出结构直接匹配需求,不需要额外做列删除、数据清洗操作

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 02:27:03