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

按ID分组重采样月度数据并计算滚动求和的技术问题

嘿,我来帮你搞定这个问题!结合你的大数据场景需求和预期输出,咱们一步步来实现:

步骤1:整理并排序原始数据

首先得把数据按id分组,并且每个id下的日期按降序排列(这样才能计算“最近4个季度行”的和,也就是最新的4条数据),同时把val转成数值类型方便计算:

import pandas as pd

# 你的原始数据
df1 = pd.DataFrame({
    'id': ['SE0000195570','SE0000195570','SE0000195570','SE0000195570','SE0000191827','SE0000191827','SE0000191827','SE0000191827', 'SE0000191827'],
    'val': ['1','2','3','4','5','6','7','8', '9'],
    'date': pd.to_datetime(['2014-10-23','2014-07-16','2014-04-29','2014-01-31','2018-10-19','2018-07-11','2018-04-20','2018-02-16','2018-12-29'])
})

# 按id升序、date降序排序,确保每个id的最新数据在前
df_sorted = df1.sort_values(['id', 'date'], ascending=[True, False]).reset_index(drop=True)
# 将val转为整数类型
df_sorted['val'] = df_sorted['val'].astype(int)

步骤2:计算每个季度行的滚动4值之和

对每个id分组后,用rolling计算最近4个季度行的val之和,min_periods=4保证只有当至少有4个数据时才计算,否则返回NaN:

df_sorted['calc'] = df_sorted.groupby('id')['val'].rolling(window=4, min_periods=4).sum().reset_index(drop=True)

这一步处理后,SE0000191827最早的那条季度行(2018-02-16)的calc正好是8+7+6+5=26,完全符合你的预期!

步骤3:生成每个id的完整月度序列

为了覆盖每个id首尾日期范围内的所有月度,我们用groupby+date_range生成完整的月度月末日期序列(避免循环,提升大数据处理效率):

# 生成每个id的首尾日期,再生成期间的所有月度月末
date_ranges = df_sorted.groupby('id').agg(
    start_date=('date', 'min'),
    end_date=('date', 'max')
).assign(
    month_end=lambda x: x.apply(lambda row: pd.date_range(row['start_date'], row['end_date'], freq='M'), axis=1)
).explode('month_end').reset_index()

# 提取需要的列
monthly_df = date_ranges[['id', 'month_end']]

步骤4:将滚动和映射到月度行

用merge_asof把月度序列和带有calc的季度数据匹配,确保每个月度行取到最近的不晚于该月的季度行的calc值:

# 将原始数据的日期转为月度月末,方便匹配
df_sorted['month_end'] = df_sorted['date'].dt.to_period('M').dt.end_time

# 确保两个数据集都按id和month_end排序(merge_asof要求)
df_sorted_matched = df_sorted.sort_values(['id', 'month_end'])
monthly_df_sorted = monthly_df.sort_values(['id', 'month_end'])

# 执行匹配,direction='backward'表示取最近的不晚于当前月度的季度行
result = pd.merge_asof(
    monthly_df_sorted,
    df_sorted_matched[['id', 'month_end', 'calc']],
    on='month_end',
    by='id',
    direction='backward'
)

最终结果示例

你查看result时,SE0000191827的2018-02-28行的calc就是26,而那些不足4个季度行的月度行(比如SE0000195570的前3个月度行)的calc会是NaN,完全符合你的需求!

性能说明

整个流程全用pandas的矢量化操作,没有循环,groupby、rolling、merge_asof都是pandas针对大数据优化过的方法,完全能适配10万+唯一id、1200万行的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:46:53