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

带日期间隔的两张表间滚动求和高效实现方案问询

高效计算分组滚动7天求和并关联基表

问题概述

现有两张数据表counts和picks,需要以counts为基表,为每一行数据按对应group计算count_date_time当日及往前7天内,picks表中number_picked的滚动求和,最终将结果合并到counts表中。

需求示例:

  • group A、时间为2022-11-11 14:00的行,求和结果为4
  • group B、时间为2022-11-14 09:00的行,求和结果为16

当前问题:逐行循环合并临时表的实现方式效率极低,无法支撑实际场景中counts表20万行、picks表百万级的规模,需要高效的向量化实现方案。

复现代码

import pandas as pd

counts = pd.DataFrame(columns=['count_date_time', 'group', 'outcome'], data=[["November 11, 2022 2:00 PM",'A',1], ["November 14, 2022 9:00 AM",'B',0]])
counts['count_date_time'] = pd.to_datetime(counts['count_date_time'])

picks = pd.DataFrame(columns=['pick_date_time','group','number_picked'], data=[["November 1, 2022 10:00 AM","A",3],
["November 1, 2022 11:00 AM","A",7],
["November 7, 2022 2:00 PM","A",4],
["November 12, 2022 3:00 PM","A",2],
["November 2, 2022 11:00 AM","B",3],
["November 8, 2022 4:00 AM","B",2],
["November 10, 2022 6:00 PM","B",4],["November 12, 2022 6:00 PM","B",10]])
picks['pick_date_time'] = pd.to_datetime(picks['pick_date_time'])

高效解决方案

以下两种方案均采用向量化操作,完全避免逐行循环,可高效处理大规模数据:

方案一:使用merge_asof区间匹配+分组求和

利用merge_asof实现同组内的时间区间匹配,再分组计算求和结果,步骤清晰且性能优异:

import pandas as pd

# 1. 为counts添加7天窗口起始时间和唯一标识
counts['start_time'] = counts['count_date_time'] - pd.Timedelta(days=7)
counts['id'] = range(len(counts))

# 2. 对两张表按group和时间排序(merge_asof要求必须排序)
picks_sorted = picks.sort_values(['group', 'pick_date_time'])
counts_sorted = counts.sort_values(['group', 'count_date_time'])

# 3. 匹配同组内pick_date_time在[start_time, count_date_time]区间的记录
merged = pd.merge_asof(
    picks_sorted,
    counts_sorted,
    by='group',
    left_on='pick_date_time',
    right_on='count_date_time',
    direction='backward'
)
merged = merged[merged['pick_date_time'] >= merged['start_time']]

# 4. 按counts的唯一id分组求和,合并回原表
rolling_sum = merged.groupby('id')['number_picked'].sum().reset_index(name='rolling_7d_sum')
result = counts.merge(rolling_sum, on='id', how='left').fillna(0)
result = result.drop(['id', 'start_time'], axis=1)

print(result)

方案二:分组滚动求和+近邻匹配

先对picks按组计算7天滚动求和,再通过merge_asof匹配到counts对应的时间点:

import pandas as pd

# 1. 对picks按group和时间排序,计算分组7天滚动求和
picks_sorted = picks.sort_values(['group', 'pick_date_time'])
picks_sorted['rolling_7d_sum'] = picks_sorted.groupby('group').rolling(
    window='7D',
    on='pick_date_time',
    closed='right'
)['number_picked'].sum().reset_index(level=0, drop=True)

# 2. 对counts排序,使用merge_asof匹配同组内最近的有效滚动求和结果
counts_sorted = counts.sort_values(['group', 'count_date_time'])
result = pd.merge_asof(
    counts_sorted,
    picks_sorted[['group', 'pick_date_time', 'rolling_7d_sum']],
    by='group',
    left_on='count_date_time',
    right_on='pick_date_time',
    direction='backward'
)

# 3. 处理无匹配数据的情况,恢复原表顺序
result['rolling_7d_sum'] = result['rolling_7d_sum'].fillna(0)
result = result.drop('pick_date_time', axis=1)
result = result.set_index(counts.index).sort_index()

print(result)

两种方案最终输出结果均符合需求:

count_date_time group  outcome  rolling_7d_sum
0 2022-11-11 14:00:00     A        1              4.0
1 2022-11-14 09:00:00     B        0             16.0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 05:50:20