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

Pandas按Type分组实现带日期差的自定义递推累积计算

pandas分组递推计算Movement字段实现方案

这类强依赖上一行计算结果的递推逻辑,无法直接通过pandas内置的cumsum/cumprod等原生累积函数实现,以下是两种可直接运行的实现方案,新手优先选第一种。


前置处理(必做)

计算前必须先做格式转换和排序,否则会出现计算错误:

import pandas as pd
import numpy as np

# 将Date列转换为标准日期格式
df['Date'] = pd.to_datetime(df['Date'])
# 按分组字段+日期升序排序,保证组内记录按时间先后排列
df = df.sort_values(by=['Type', 'Date']).reset_index(drop=True)

注:你问题里写的系数0,0001是欧洲数字写法,Python里小数点用点表示,实际计算时要写为0.0001


方案1:分组逐行递推(逻辑直观,新手友好)

直接给每个分组写独立的递推逻辑,代码可读性高,方便排查错误,10万行以内数据量性能完全够用:

def calc_group_movement(group):
    movement_res = []
    # 初始化上期值缓存
    last_mov = None
    last_date = None
    for _, row in group.iterrows():
        dep = row['deposit']
        wd = row['withdrawal']
        cur_date = row['Date']
        if last_mov is None:
            # 组内首条记录计算规则
            cur_mov = dep - wd
        else:
            # 非首条记录:先计算和上一条记录的间隔天数
            day_gap = (cur_date - last_date).days
            cur_mov = last_mov * (1 + day_gap * 0.0001) + dep - wd
        movement_res.append(cur_mov)
        # 更新缓存值供下一行计算使用
        last_mov = cur_mov
        last_date = cur_date
    group['Movement'] = movement_res
    return group

# 按Type分组应用计算逻辑
df = df.groupby('Type', group_keys=False).apply(calc_group_movement)

运行完直接打印df即可看到和示例一致的计算结果。


方案2:Numba加速方案(适合百万级以上大数据量)

如果数据量很大,逐行循环速度慢,可以用Numba做JIT编译加速,计算逻辑和方案1完全一致,运行速度可以提升10~100倍:

# 先安装依赖:pip install numba
from numba import jit

@jit(nopython=True)
def _fast_calc(dates_arr, dep_arr, wd_arr):
    res_len = len(dates_arr)
    mov_arr = np.empty(res_len, dtype=np.float64)
    # 首行计算
    mov_arr[0] = dep_arr[0] - wd_arr[0]
    # 逐行递推
    for i in range(1, res_len):
        day_gap = (dates_arr[i] - dates_arr[i-1]) / np.timedelta64(1, 'D')
        mov_arr[i] = mov_arr[i-1] * (1 + day_gap * 0.0001) + dep_arr[i] - wd_arr[i]
    return mov_arr

# 分组批量计算
df['Movement'] = df.groupby('Type', group_keys=False).apply(
    lambda x: _fast_calc(x['Date'].values, x['deposit'].values, x['withdrawal'].values)
).explode().astype(np.float64)

注意事项

  • 不要跳过排序步骤,如果组内日期顺序颠倒,取到的上期日期和上期Movement值都是错的
  • 日期间隔必须取整数天参与计算,直接用两个datetime对象相减得到的Timedelta类型无法直接参与数值乘法
  • 计算前先检查deposit、withdrawal字段的空值,空值参与运算会导致整列结果返回NaN

内容的提问来源于stack exchange,提问作者Fernando A.W.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 18:39:34