为何Pandas+Numba代码运行速度慢于Pandas+纯Python代码?
问题:Numba加速DataFrame单元格处理反而更慢?
我尝试对DataFrame的每个单元格应用函数,运行时长测试显示:当矩阵规模为1000x1000时,Numba代码比纯Python代码慢6-7倍;当规模为10000x10000时,慢2-3倍。已多次运行代码排除编译时间对总时长的影响,请问我忽略了什么?
测试代码
import time import numpy as np from numba import jit import pandas as pd vcf = pd.DataFrame(np.full(shape=(10_000,10_000), fill_value='./.')) time1 = time.perf_counter() @jit(cache=True) def jit_func(x): if x == './.': return 1 else: return 0 vcf.applymap(jit_func) print('JIT', time.perf_counter() - time1) time1 = time.perf_counter() vcf.applymap(lambda x: 1 if x=='./.' else 0) print('LAMBDA', time.perf_counter() - time1) time1 = time.perf_counter() def python_func(x): if x == './.': return 1 else: return 0 vcf.applymap(python_func) print('PYTHON', time.perf_counter() - time1)
测试输出
JIT 464.7864613599959 LAMBDA 158.36754451994784 PYTHON 122.22150028299075
原因分析与优化方案
1. Numba的调用开销抵消了加速效果
applymap是逐单元格调用函数,每次调用Numba编译的jit_func时,都要经历Python到Numba的上下文切换,这个额外开销远大于Numba对单条简单判断的加速。而纯Python函数在applymap中的调用没有这个切换成本,所以反而更快。
2. 错误使用逐元素处理,应该用向量化操作
Pandas/NumPy的核心优势是向量化操作,针对整个数组批量处理,完全避开逐元素循环的开销。你的需求可以用一行向量化代码实现,速度会快几个数量级:
time1 = time.perf_counter() result = vcf.eq('./.').astype(int) print('VECTORIZED', time.perf_counter() - time1)
这种方式直接对整个DataFrame做相等判断,再转成整数,不需要任何逐元素函数调用。
3. Numba的正确打开方式
如果一定要用Numba,不要逐单元格调用,而是把DataFrame转成NumPy数组,然后写一个处理整个数组的Numba函数:
@jit(nopython=True) def numba_vectorized(arr): res = np.empty_like(arr, dtype=np.int32) for i in range(arr.shape[0]): for j in range(arr.shape[1]): res[i,j] = 1 if arr[i,j] == './.' else 0 return res time1 = time.perf_counter() result = pd.DataFrame(numba_vectorized(vcf.values)) print('NUMBA VECTORIZED', time.perf_counter() - time1)
这种方式利用Numba对循环的加速,避免了逐元素调用的开销,性能会远优于原来的applymap+jit_func。
内容的提问来源于stack exchange,提问作者YKY
相关产品推荐
相关产品推荐

