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

行列计算存在依赖需按序执行,能否摆脱Pandas迭代提速?

优化带行依赖的Pandas迭代计算速度

当前存在带行依赖的计算场景:col3依赖当前行的col1和col2,col1依赖上一行的col3,这类计算无法直接用Pandas向量化操作。针对50万行6列的DataFrame:

  • 直接迭代DataFrame耗时2-3分钟
  • 转为Numpy数组迭代后耗时约10秒,需进一步优化提速

示例代码

d = {'col1': [1, 0, 0, 0], 'col2': [0, 'a', 'a', 0], 'col3': [0, 0, 0, 0]}
df = pd.DataFrame(data=d, index=[0, 1, 2, 3])

for i in range(df.shape[0]):
    if i > 0:
        df.iloc[i, 0] = df.iloc[i-1, 2]
    if df.iloc[i, 1] == 'a':
        df.iloc[i, 2] = df.iloc[i, 0] + 1
    else:
        df.iloc[i, 2] = df.iloc[i, 0]

优化方案

1. Numba加速Numpy迭代

Numba能把Python函数编译为机器码,大幅降低循环开销。针对当前逻辑,用Numba装饰器处理数组:

import numba
import numpy as np
import pandas as pd

@numba.jit(nopython=True)  # nopython模式性能最优
def compute(arr):
    rows = arr.shape[0]
    for i in range(rows):
        if i > 0:
            arr[i, 0] = arr[i-1, 2]
        if arr[i, 1] == 'a':
            arr[i, 2] = arr[i, 0] + 1
        else:
            arr[i, 2] = arr[i, 0]
    return arr

# 转换为numpy数组(根据实际数据类型调整,这里用object兼容字符串)
df_arr = df.to_numpy(dtype=object)
df_arr = compute(df_arr)
# 转回DataFrame
result_df = pd.DataFrame(df_arr, columns=df.columns, index=df.index)

优化点:如果col2是固定类别,把'a'映射为整数(比如1),其他值映射为0,避免Numba处理字符串的额外开销,能再提一波速度。

2. 手动向量化(针对固定逻辑推导)

如果业务逻辑可拆解为数学规律,比如观察到:

  • 初始col3 = col1[0]
  • 当col2为'a'时,col3 = 上一行col3 +1;否则等于上一行col3
  • col1就是上一行的col3

可以直接用Pandas的cumsum和shift实现全向量化计算,这是速度最快的方案:

# 设置初始值
df['col3'] = df['col1'].iloc[0]
# 计算每一行的增量:col2为'a'则加1,否则加0
increments = (df['col2'] == 'a').astype(int)
# 累加增量得到col3
df['col3'] = df['col3'].iloc[0] + increments.cumsum()
# col1取上一行的col3,shift填充初始值
df['col1'] = df['col3'].shift(fill_value=df['col1'].iloc[0])

3. Cython编写扩展(极致性能需求)

如果Numba仍达不到性能要求,可以用Cython把循环逻辑写成C级代码,编译后调用,性能接近纯C。但需要额外的编译步骤,适合复杂且对性能极致要求的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 13:40:33