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

Pandas如何通过groupby实现按日期递增的滚动数据切片聚合

基于pandas原生方法的滚动累计聚合实现

问题说明

现有跑步群体运动数据集,单条记录包含跑者姓名、跑步日期、跑步里程三个字段,需要生成随日期推进、统计范围持续扩大的累计数据切片,按跑者聚合得到截至每个日期节点的累计运动数据。原有逐日期循环筛选的实现方式在大数据量下性能较差,可通过pandas原生分组、重索引、累计计算逻辑替代,性能提升显著。

示例数据集构造代码:

import pandas as pd

df=pd.DataFrame({'name': 'Jack Jill Bob Bella Norm Nella Jack Jill Bob Bella Norm Nella Jack Jill Bob Bella Norm Nella'.split(),
                'date': '05-04-2021 05-04-2021 05-04-2021 06-04-2021 05-04-2021 06-04-2021 06-04-2021 08-04-2021 11-04-2021 08-04-2021 11-04-2021 08-04-2021 11-04-2021 11-04-2021 15-04-2022 15-04-2022 18-04-2022 19-04-2022'.split(),
                'km': [5.85, 5.18, 13.58, 14.45, 14.58, 11.14, 8.85, 10.77, 12.54, 7.09, 7.69, 11.64, 9.82, 11.20, 10.33, 11.31, 14.66, 12.56]})

df['date']=pd.to_datetime(df['date'], infer_datetime_format=True)

原有循环实现参考:

for d in df.date.unique():
    rolling=df[df.date <= d].groupby('name').sum()
    rolling['date']=d

高性能原生实现代码

核心逻辑为先补全所有日期-跑者的完整组合,再按跑者分组做累计计算,全程仅需两次分组操作,无需逐日期遍历全表:

# 1. 先聚合得到每个日期下单个跑者的当日运动总里程
daily_agg = df.groupby(['date', 'name'], as_index=False)['km'].sum()

# 2. 生成所有唯一日期、所有跑者的完全交叉索引,避免漏算无跑步记录的跑者
full_cross_index = pd.MultiIndex.from_product(
    [df['date'].sort_values().unique(), df['name'].unique()],
    names=['date', 'name']
)

# 3. 重索引补全缺失记录,当日无跑步记录的里程填0
daily_full = daily_agg.set_index(['date', 'name']).reindex(full_cross_index, fill_value=0).reset_index()

# 4. 按跑者分组做累计求和,得到截至每个日期的累计里程
daily_full['total_km'] = daily_full.sort_values('date').groupby('name')['km'].cumsum()

最终输出的daily_full表中,每一行对应某一日期节点下单个跑者的累计跑步里程,和原有循环逻辑输出结果完全一致。

复杂聚合逻辑扩展

如果需要实现除求和外的更复杂聚合(比如累计跑步次数、单次最高里程、累计平均里程等),可以用分组后的expanding()扩展窗口实现,支持自定义聚合函数:

# 按跑者分组,对历史全量数据做多维度聚合
complex_agg = daily_full.sort_values(['name', 'date']).groupby('name')['km'].expanding().agg(
    total_km = 'sum',
    run_count = lambda x: (x > 0).sum(),
    max_single_km = 'max',
    avg_km = 'mean'
).reset_index(drop=True)

# 拼接日期、姓名字段得到最终结果
result = pd.concat(
    [daily_full[['date', 'name']].sort_values(['name', 'date']).reset_index(drop=True), complex_agg],
    axis=1
)

性能说明

  • 原有循环方案时间复杂度为O(nd)*,n为总记录数,d为唯一日期数,每遍历一个日期就要全表扫描做一次筛选和分组,十万级以上数据性能衰减明显。
  • 原生实现方案时间复杂度接近O(n),仅需固定次数的全表操作,百万级数据可在秒级完成计算。

内容的提问来源于stack exchange,提问作者Dave-C

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 10:03:20