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

数据无法向量化时pandas iterrows()的提速替代方案咨询

核心问题根源

你最开始的代码耗时呈指数级增长,本质是写了O(n²)复杂度的双重遍历:外层用iterrows()逐行迭代的同时,内层又调用了一次df.apply(..., axis=1)做全表逐行计算,数据量每翻10倍,计算量会涨100倍,再叠加上pandas逐行操作的固有开销,耗时感知会非常明显。就算是你更新后的单轮iterrows()写法,本身也存在大量不必要的性能损耗,远没有达到最优效率。

另外明确说明:手动把数据拆成更小的分组对单线程计算没有任何提速效果,反而会增加拆分、拼接的额外开销,只有做并行计算的时候才需要按CPU核心数做任务分片。

可落地的提速方案(按提速幅度从高到低排序)
  • 最高优先级:绕开pandas对象做原生列表循环
    这是纯Python循环场景下速度最快的写法,比你现在的iterrows()写法快10~50倍。核心思路是提前把需要用到的列转成Python原生列表,循环过程完全不碰pandas对象的索引、属性访问逻辑,所有计算结果存在普通列表里,最后一次性赋值给DataFrame,避免逐行写表的开销:

    # 提前提取需要的字段为原生列表
    col1_vals = df["col1"].tolist()
    col2_vals = df["col2"].tolist()
    # 其他需要传入some_func的字段同理提前提取
    result = []
    for c1, c2 in zip(col1_vals, col2_vals):
        result.append(some_func(c1, c2))
    # 一次性写入新列
    df["new_col"] = result
    
  • 次选:用itertuples()替代iterrows()
    如果不想提前拆列表,直接把迭代方法换成itertuples()就能获得10~20倍的提速。itertuples()返回的是轻量命名元组,不会像iterrows()那样为每一行构造新的Series对象、做重复类型推断,访问字段值的开销极低:

    result = []
    # index=True会保留行索引,方便需要定位行的场景
    for row in df.itertuples(index=True):
        res = some_func(row.col1, row.col2) # 直接用列名当属性访问即可
        result.append(res)
    df["new_col"] = result
    
  • 复杂计算场景:用并行apply替代单线程循环
    如果some_func()是计算密集型逻辑(比如涉及复杂数值计算、字符串处理),可以用并行计算库把逐行计算任务分发到多个CPU核心跑,比单线程循环再快数倍,写法不需要大改:

    # 以swifter为例,会自动判断是否可以向量化,无法向量化时自动启用并行计算
    import swifter
    df["new_col"] = df.swifter.apply(lambda x: some_func(x["col1"], x["col2"]), axis=1)
    

    注意用并行计算时,some_func()必须是纯函数,不依赖外部可变状态,否则会出现计算结果错误。

  • 长期优化方向:尽量用向量化操作替代循环
    如果后续可以把some_func()的逻辑拆成支持numpy数组运算的片段,直接用pandas/numpy原生向量化操作实现,速度会比纯Python循环快100~1000倍,是pandas数据处理的最优方案。

避坑提醒
  • 绝对不要在逐行循环内部嵌套全表级别的apply、iterrows操作,这是导致你最初代码耗时指数级上涨的核心错误。
  • 尽量不要在循环内部用df.loc[]逐行赋值,逐行修改DataFrame的开销远大于最后一次性整列赋值。
  • 非必要不要用iterrows(),这个API本身的固有开销在数据量大于1万行之后就会变得非常明显。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 03:18:29