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

Pandas按id分组创建依赖前序行值的新列并逐行更新的实现方法

Pandas分组逐行递推计算新列实现方案

问题背景

学习pandas过程中遇到如下结构的DataFrame:

index  Random  id  diff  pct
0 2018-01-01      31   1     3    1
1 2018-01-02      11   1     2    2
2 2018-01-03      21   1     4    0
3 2018-01-04      23   2     1    0
4 2018-01-05      43   2     6    3
5 2018-01-06      42   2     1    1
6 2018-01-07      51   3     2    5
7 2018-01-08      47   3     2    0
8 2018-01-09      49   3     3    2
9 2018-01-10      22   3     1    3

需求为基于判断条件创建recommend列与Random_new列,核心要求是Random_new的计算存在行级依赖:当前行计算得到的新值需要作为同组后续行的计算基准,且所有计算按id分组独立执行。
期望输出结构如下:

index  Random  id  diff  pct recommend  Random_new
0 2018-01-01      31   1     3    1         Y          32
1 2018-01-02      31   1     2    2         N          32
2 2018-01-03      31   1     4    0         Y          36
3 2018-01-04      23   2     1    0         Y          24
4 2018-01-05      23   2     6    3         Y          27
5 2018-01-06      23   2     1    1         N          27
6 2018-01-07      51   3     2    5         N          51
7 2018-01-08      51   3     2    0         Y          53
8 2018-01-09      51   3     3    2         Y          56
9 2018-01-10      51   3     1    3         N          56

尝试过np.where实现,但该方法仅支持静态向量化计算,无法处理逐行依赖前序计算结果的递推逻辑;尝试编写for循环但未跑通。

计算规则

  • 若当前行pct < diff,则recommend取值为Y,Random_new = 当前行Random值 + 当前行diff值
  • 若当前行pct >= diff,则recommend取值为N,Random_new = 同组上一行的Random_new值
  • 同组内计算得到的Random_new值需要向后传递,作为后续行的计算基准
  • 不同id分组的计算完全独立,互不干扰

实现代码

这类带状态传递的递推计算无法通过普通向量化操作完成,按分组逐行迭代、维护计算状态即可实现,代码如下:

import pandas as pd

# --------------- 初始化示例数据 ---------------
df = pd.DataFrame({
    'index': pd.date_range(start='2018-01-01', periods=10),
    'Random': [31,11,21,23,43,42,51,47,49,22],
    'id': [1,1,1,2,2,2,3,3,3,3],
    'diff': [3,2,4,1,6,1,2,2,3,1],
    'pct': [1,2,0,0,3,1,5,0,2,3]
})

# --------------- 核心计算逻辑 ---------------
def process_group(group_df):
    # 存储单组计算结果
    calc_result = []
    # 初始化上一行计算值为None,标记组内第一行
    last_random_new = None
    # 逐行遍历组内数据
    for _, row in group_df.iterrows():
        if row['pct'] < row['diff']:
            # 满足更新条件,计算新值
            current_random_new = row['Random'] + row['diff']
            current_rec = 'Y'
        else:
            # 不满足更新条件,取上一行值;组内第一行直接取当前行Random作为初始值
            current_random_new = last_random_new if last_random_new is not None else row['Random']
            current_rec = 'N'
        calc_result.append((current_rec, current_random_new))
        # 更新状态,供下一行使用
        last_random_new = current_random_new
    # 将结果赋值回分组DataFrame
    group_df[['recommend', 'Random_new']] = calc_result
    return group_df

# 先按id和时间排序保证行顺序正确,再分组应用计算逻辑
df = df.sort_values(by=['id', 'index']).groupby('id', group_keys=False).apply(process_group)

注意事项

  • 计算前必须保证DataFrame按id和业务时间字段(本例中为index列)排序,否则逐行递推的顺序会出错,得到错误结果
  • 如果数据量较大,iterrows性能一般,可以换用itertuples迭代提升速度,逻辑完全一致
  • 如果需要直接更新原Random列而非新建Random_new,只需要把函数内赋值的列名改成Random即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 13:09:18