Pandas中替代apply方法:基于多列创建新列的高效方案
嘿,我完全懂这种痛点!400万行的DataFrame用apply跑十几秒确实让人头疼——毕竟apply本质是Python级别的逐行循环,对于大数据量来说效率太低了。咱们得换个思路,用Pandas/NumPy的向量化操作或者编译型方法来提速,下面给你几个亲测有效的方案:
方案1:优先用Pandas内置的向量化函数
如果你的自定义逻辑能拆解成Pandas已经实现的向量化方法,这是最快的选择——这些函数都是用C实现的,完全避开了Python循环。比如:
- 条件判断用
np.where或者df.loc的布尔索引 - 区间划分用
pd.cut/pd.qcut - 字符串处理用
str开头的方法(比如str.contains、str.extract) - 数学运算直接用列之间的加减乘除
举个例子,如果你之前用apply判断某列值的区间:
# 慢的apply写法 def get_level(x): if x > 100: return 'High' elif 50 <= x <=100: return 'Medium' else: return 'Low' df['level'] = df['value'].apply(get_level)
换成向量化写法,速度能提升几十倍:
# 快的向量化写法 import numpy as np df['level'] = np.where(df['value']>100, 'High', np.where(df['value']>=50, 'Medium', 'Low')) # 或者用pd.cut更简洁 bins = [-np.inf, 50, 100, np.inf] labels = ['Low', 'Medium', 'High'] df['level'] = pd.cut(df['value'], bins=bins, labels=labels)
方案2:用NumPy数组实现复杂逻辑
如果你的逻辑比较复杂,Pandas内置函数不够用,就把列转成NumPy数组处理——NumPy的数组操作也是C级别的,比Python循环快得多。比如处理多列的复杂逻辑:
import numpy as np def complex_logic(col1, col2): # 用NumPy的布尔掩码处理多条件 result = np.empty(len(col1), dtype='U10') mask = (col1 > 10) & (col2 < 5) result[mask] = 'Pass' result[~mask] = 'Fail' # 可以叠加更多掩码逻辑 return result # 把列转成NumPy数组传入 df['result'] = complex_logic(df['col1'].values, df['col2'].values)
方案3:用Numba编译自定义函数
如果你的逻辑实在没法向量化(比如有很多分支、依赖行与行的计算),试试Numba——它能把Python函数编译成机器码,速度接近C。注意尽量用NumPy数组而不是Pandas Series传入:
from numba import jit # nopython模式下速度最快,避免Python对象的开销 @jit(nopython=True) def numba_logic(arr): n = len(arr) result = np.empty(n, dtype='U10') for i in range(n): # 这里可以写任意复杂的Python逻辑 if arr[i] > 100: result[i] = 'High' elif arr[i] >= 50: result[i] = 'Medium' else: result[i] = 'Low' return result df['level'] = numba_logic(df['value'].values)
方案4:彻底放弃itertuples/iterrows
你提到itertuples提升不明显,这很正常——它本质还是逐行循环,只是比iterrows少了一些属性查找的开销,但对于400万行来说还是太慢。只有当所有向量化方法都无法实现你的逻辑时,才考虑用它,而且要尽量把循环内的操作简化(比如提前把列转成局部变量)。
额外优化小技巧
- 优化数据类型:把不需要高精度的数值列转成
int32/float32,字符串列转成category类型(如果重复值多),能减少内存占用并提升速度。 - 分批处理:如果内存吃紧,可以把DataFrame分成几块处理,最后再合并结果。
- 先测试再跑全量:用
df.sample(10000)先验证逻辑正确性,再跑400万行的全量数据,避免浪费时间。
我之前处理过类似规模的数据集,用向量化或者Numba把15秒的操作压到了0.2秒以内,你可以根据自己的具体逻辑选择合适的方案!
内容的提问来源于stack exchange,提问作者swathis
相关产品推荐
相关产品推荐

