如何在Pandas中逐步生成两个互相依赖的递推列?
基于前一行递推生成Pandas列的原生解决方案
针对你需要生成互相依赖的b、c列的需求,确实可以用Pandas原生方法实现,不需要手动循环。首先明确你的递推规则:
- 第一行的b、c基于默认值1计算:
b = a + 2*default,c = a + default - 从第二行开始,每行的b、c依赖前一行的a、b、c:
b = 上一行a + 2*上一行cc = 上一行a + 上一行b
方法1:使用expanding().apply()(纯Pandas原生)
这个方法利用Pandas的扩展窗口(expanding window)来传递每一步的状态,窗口从第一行逐步扩大到当前行,每一步计算依赖窗口内的前一行数据:
import pandas as pd # 初始化DataFrame df = pd.DataFrame({'a': [1,2,3,4]}) default = 1 def compute_bc(window): if len(window) == 1: # 处理第一行,用默认值 b_val = window['a'].iloc[0] + 2 * default c_val = window['a'].iloc[0] + default return pd.Series([b_val, c_val], index=['b', 'c']) else: # 提取前一行的a、b、c值 prev_a = window['a'].iloc[-2] prev_b = window['b'].iloc[-2] prev_c = window['c'].iloc[-2] # 计算当前行的b、c curr_b = prev_a + 2 * prev_c curr_c = prev_a + prev_b return pd.Series([curr_b, curr_c], index=['b', 'c']) # 应用扩展窗口计算 df[['b', 'c']] = df.expanding().apply(compute_bc, raw=False)
运行后得到的结果完全符合你的期望:
a b c 0 1 3 2 1 2 5 4 2 3 10 7 3 4 17 13
方法2:结合itertools.accumulate(高效简洁)
如果追求更高的计算效率,可以用itertools.accumulate来处理递推逻辑,它会自动把每一步的输出作为下一步的输入,再结合Pandas赋值:
import pandas as pd import itertools df = pd.DataFrame({'a': [1,2,3,4]}) default = 1 # 初始化第一行的b、c df.loc[0, 'b'] = df.loc[0, 'a'] + 2 * default df.loc[0, 'c'] = df.loc[0, 'a'] + default # 定义递推步骤:接收前一行的(a, b, c)和当前行的a,返回当前行的(a, b, c) def recursive_step(prev_vals, curr_a): prev_a, prev_b, prev_c = prev_vals curr_b = prev_a + 2 * prev_c curr_c = prev_a + prev_b return (curr_a, curr_b, curr_c) # 从第二行开始累积计算 initial_state = (df.loc[0, 'a'], df.loc[0, 'b'], df.loc[0, 'c']) results = list(itertools.accumulate(df['a'][1:], recursive_step, initial=initial_state)) # 把结果赋值回DataFrame for idx, (a_val, b_val, c_val) in enumerate(results, start=1): df.loc[idx, 'b'] = b_val df.loc[idx, 'c'] = c_val
为什么不推荐rolling方法?
rolling()是针对固定大小窗口的聚合计算(比如滚动均值、滚动求和),而你的场景需要的是状态持续传递的递推——每一步的结果都依赖上一步的输出,窗口是不断扩大的,因此expanding()更匹配你的需求。
内容的提问来源于stack exchange,提问作者Gulzar
相关产品推荐
相关产品推荐

