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

如何基于向量化操作高效实现不同DataFrame两列的函数批量调用

高效处理两个DataFrame列的两两函数调用

嘿,我太懂你在大数据集下用嵌套循环或者itertools.product卡得要死的痛苦了!这种Python层面的逐元素循环天生效率极低,尤其是当两个DataFrame的Name列规模上去之后,简直是灾难。下面给你几个靠谱的优化方向,从简单易实现到进阶加速都有,按需选用:

1. 先做交叉连接,再批量处理

首先可以用Pandas的交叉连接(Cross Join)生成所有Name的组合对,然后想办法批量应用你的func,而不是逐行调用。

生成交叉连接的方法很简单,给两个DataFrame加个临时的相同键,然后合并:

import pandas as pd

# 给两个DF加临时键
df1 = df1.assign(temp_key=1)
df2 = df2.assign(temp_key=1)

# 交叉连接得到所有组合
cross_joined = df1.merge(df2, on="temp_key").drop("temp_key", axis=1)

接下来分两种情况处理:

  • 如果你的func本身支持接收Pandas Series作为输入(也就是能批量处理字符串),直接调用就行:
    cross_joined["result"] = func(cross_joined["Name_x"], cross_joined["Name_y"])
    
  • 如果func只能处理单个字符串,别用apply(本质还是行循环),而是把func向量化。比如用numpy.vectorize包装一下:
    import numpy as np
    
    vec_func = np.vectorize(func)
    cross_joined["result"] = vec_func(cross_joined["Name_x"], cross_joined["Name_y"])
    
    注意:np.vectorize本质是个“伪向量化”包装器,底层还是循环,但比你手动写嵌套循环要高效不少,尤其是结合Numpy的底层优化。

2. 用Numpy广播直接生成二维结果矩阵

如果不需要保留所有组合的DataFrame,只是要得到两两调用后的结果矩阵,用Numpy广播会更高效:

arr1 = df1["Name"].to_numpy()
arr2 = df2["Name"].to_numpy()

# 把arr1变成(n,1)形状,arr2保持(1,m)形状,利用广播生成(n,m)的组合对
# 先把func向量化
vec_func = np.vectorize(func)
result_matrix = vec_func(arr1[:, None], arr2)

这样得到的result_matrix是一个二维数组,result_matrix[i,j]就是func(df1['Name'][i], df2['Name'][j])的结果。

3. 终极加速:用Numba编译自定义函数

如果你的func是复杂的纯Python逻辑,np.vectorize提升有限,那试试用Numba把它编译成机器码,这能带来数量级的速度提升:

首先安装Numba(pip install numba),然后改写你的函数:

from numba import njit
import numpy as np

# 用@njit装饰器编译函数,注意要兼容Numpy数组操作
@njit
def numba_accelerated_func(arr_a, arr_b):
    n = arr_a.shape[0]
    m = arr_b.shape[0]
    result = np.empty((n, m), dtype=np.int_)  # 提前分配结果数组,避免动态扩容
    for i in range(n):
        for j in range(m):
            result[i, j] = func(arr_a[i], arr_b[j])  # 这里调用你原来的func逻辑
    return result

# 调用加速后的函数
arr1 = df1["Name"].to_numpy()
arr2 = df2["Name"].to_numpy()
result_matrix = numba_accelerated_func(arr1, arr2)

第一次运行会有编译开销,但之后的调用都会直接跑机器码,比纯Python循环快几十甚至上百倍。

4. 特殊场景:用专门库处理字符串任务

如果你的func是字符串相似度计算(比如编辑距离、模糊匹配)这类常见任务,别自己写函数了,用专门的优化库,比如rapidfuzz(纯C++实现,速度拉满):

安装后直接用批量接口:

from rapidfuzz import fuzz

arr1 = df1["Name"].to_numpy()
arr2 = df2["Name"].to_numpy()

# 直接生成所有两两相似度得分的矩阵
result_matrix = fuzz.ratio(arr1[:, None], arr2)

这种库的效率是纯Python函数完全比不了的,能轻松处理十万级别的数据。


总结一下优先级:

  1. 优先把func改造成支持Pandas/Numpy批量输入的形式,用内置方法替代自定义循环;
  2. 若无法改造,用Numba编译你的循环逻辑;
  3. 特殊字符串任务直接用专门的优化库;
  4. 最后才考虑np.vectorize或者交叉连接+apply。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:45:58