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

Pandas rolling可变窗口报错及金额按周期向前回填方案求解

解决方案

pandas 原生 rolling 方法的 window 参数仅支持固定整数或固定时间偏移量,不支持传入序列实现逐行动态窗口,因此你之前的写法会抛出数值类型错误。
针对3000万级别的大数据量,推荐使用以下高性能实现方案,完全匹配你的需求:

前置预处理

首先确保数据按ID分组、日期升序排列,并完成格式转换:

import pandas as pd
import numpy as np

# 日期格式转换 + 排序
df['DATE'] = pd.to_datetime(df['DATE'], format='%d-%m-%Y')
df = df.sort_values(['ID', 'DATE']).reset_index(drop=True)
# 空金额转为0,避免计算报错
df['AMOUNT'] = pd.to_numeric(df['AMOUNT'], errors='coerce').fillna(0)

核心计算逻辑

你的需求本质是:每个非空的AMOUNT值,会覆盖从当前行往前数VARIABLE_DISTRIBUTION - 1行到当前行的区间,区间内的REPEAT_AMOUNT统一取该AMOUNT值,后出现的有效值会覆盖前面的重叠区间。
我们通过向量化区间赋值实现,性能远高于逐行apply或循环:

def calc_repeat_amount(group):
    group_len = len(group)
    res = np.full(group_len, np.nan)
    # 提取当前分组的数值数组
    amt_arr = group['AMOUNT'].values
    dist_arr = group['VARIABLE_DISTRIBUTION'].values
    # 筛选有有效值的位置
    valid_idx = np.where(amt_arr > 0)[0]
    if valid_idx.size == 0:
        group['REPEAT_AMOUNT'] = res
        return group
    # 计算每个有效值的覆盖区间
    start_pos = np.maximum(0, valid_idx - dist_arr[valid_idx] + 1)
    end_pos = valid_idx + 1
    valid_amt = amt_arr[valid_idx]
    # 批量赋值,后值自动覆盖前值重叠部分
    for s, e, val in zip(start_pos, end_pos, valid_amt):
        res[s:e] = val
    group['REPEAT_AMOUNT'] = res
    return group

# 按ID分组计算
df = df.groupby('ID', group_keys=False).apply(calc_repeat_amount)
# 可选:将空值转为示例中的'-'格式
df['REPEAT_AMOUNT'] = df['REPEAT_AMOUNT'].fillna('-')

超大数据量优化

如果单节点内存无法承载全量数据,可以替换为Dask框架分块计算,逻辑和上述代码完全一致,仅需将pandas接口替换为Dask对应接口即可,无需调整核心逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 16:06:08