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

如何优化依赖前序值的Pandas列计算以提升性能

问题描述

现有一个DataFrame,其中final_lb和final_ub列的每行计算严格依赖前一行的结果,当前使用Python for循环实现,程序性能受限于循环的解释执行开销。DataFrame结构如下:

close      basic_lb      basic_ub  final_lb  final_ub
0   18801.70  18823.800000  18823.800000       0.0       0.0
1   18794.65  18750.575000  18845.675000       0.0       0.0
2   18827.30  18758.725000  18864.925000       0.0       0.0
3   18862.10  18786.850000  18904.450000       0.0       0.0
4   18849.25  18794.340000  18911.310000       0.0       0.0
5   18850.70  18791.143500  18903.556500       0.0       0.0
6   18859.65  18798.624150  18907.625850       0.0       0.0
7   18840.80  18795.519235  18904.930765       0.0       0.0
8   18831.95  18782.764812  18887.835188       0.0       0.0
9   18847.00  18787.678330  18891.271670       0.0       0.0
10  18815.00  18772.292997  18888.957003       0.0       0.0
11  18812.30  18759.911198  18870.938802       0.0       0.0
12  18816.95  18752.947578  18863.402422       0.0       0.0
13  18817.60  18762.375320  18869.674680       0.0       0.0
14  18815.15  18764.835288  18864.914712       0.0       0.0

当前使用的循环代码:

for i in range(1, len(data)):
    data['final_ub'].iat[i] = data['basic_ub'].iat[i] if data['basic_ub'].iat[i] < data['final_ub'].iat[i - 1] or data['close'].iat[i - 1] > data['final_ub'].iat[i - 1] else data['final_ub'].iat[i - 1]
    data['final_lb'].iat[i] = data['basic_lb'].iat[i] if data['basic_lb'].iat[i] > data['final_lb'].iat[i - 1] or data['close'].iat[i - 1] < data['final_lb'].iat[i - 1] else data['final_lb'].iat[i - 1]
优化方案

1. 使用Numba JIT编译加速循环

Python原生for循环的性能瓶颈在于解释执行的开销,Numba可将Python函数编译为机器码,大幅提升循环效率,且逻辑与原代码完全一致,是最推荐的方案。

代码示例:

import numba as nb
import numpy as np

@nb.njit  # 编译为机器码,默认禁用并行(因计算依赖前序结果)
def calculate_bounds(close, basic_lb, basic_ub, initial_lb, initial_ub):
    n = len(close)
    final_lb = np.zeros(n, dtype=np.float64)
    final_ub = np.zeros(n, dtype=np.float64)
    final_lb[0] = initial_lb
    final_ub[0] = initial_ub
    
    for i in range(1, n):
        # 计算final_ub[i]
        if basic_ub[i] < final_ub[i-1] or close[i-1] > final_ub[i-1]:
            final_ub[i] = basic_ub[i]
        else:
            final_ub[i] = final_ub[i-1]
        
        # 计算final_lb[i]
        if basic_lb[i] > final_lb[i-1] or close[i-1] < final_lb[i-1]:
            final_lb[i] = basic_lb[i]
        else:
            final_lb[i] = final_lb[i-1]
    
    return final_lb, final_ub

# 传入numpy数组计算(Numba对numpy支持更优)
final_lb, final_ub = calculate_bounds(
    data['close'].values,
    data['basic_lb'].values,
    data['basic_ub'].values,
    data['final_lb'].iloc[0],
    data['final_ub'].iloc[0]
)

# 赋值回DataFrame
data['final_lb'] = final_lb
data['final_ub'] = final_ub

优势:

  • 编译后性能接近原生C/C++水平,百万级数据量下速度可提升几十至上百倍
  • 无需修改原计算逻辑,迁移成本低

2. Cython手动编译循环(极致性能需求)

若Numba无法满足极致性能要求,可使用Cython编写循环代码,手动指定变量类型进一步优化。但需学习Cython语法,复杂度较高,仅适合核心性能瓶颈场景。

3. 结果验证

运行优化代码后,可通过以下方式验证结果与原循环一致:

# 保存原循环结果
data_old = data.copy()
for i in range(1, len(data_old)):
    data_old['final_ub'].iat[i] = data_old['basic_ub'].iat[i] if data_old['basic_ub'].iat[i] < data_old['final_ub'].iat[i - 1] or data_old['close'].iat[i - 1] > data_old['final_ub'].iat[i - 1] else data_old['final_ub'].iat[i - 1]
    data_old['final_lb'].iat[i] = data_old['basic_lb'].iat[i] if data_old['basic_lb'].iat[i] > data_old['final_lb'].iat[i - 1] or data_old['close'].iat[i - 1] < data_old['final_lb'].iat[i - 1] else data_old['final_lb'].iat[i - 1]

# 对比结果
print(data[['final_lb', 'final_ub']].equals(data_old[['final_lb', 'final_ub']]))  # 应输出True

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 02:47:06