apply慢因单线程执行且每次调用触发类型推断与索引对齐;向量化可提速10–100倍;swifter仅优化DataFrame/Series.apply,不支持groupby等场景,多进程需注意序列化与内存开销。

为什么 apply 慢得明显?不是写法问题,是机制问题
pandas.DataFrame.apply 默认单线程逐行/逐列执行,底层没有自动并行,哪怕你机器有 16 核,它也只用 1 个。更关键的是:每次调用都会触发 pandas 的类型推断和索引对齐,开销远超纯 Python 函数本身。尤其当 apply 里混用 axis=1 和自定义逻辑(比如字符串切片+条件判断),性能会断崖式下跌。
- 如果函数能向量化(如用
str.contains替代lambda x: 'abc' in x),优先改写,速度提升常达 10–100 倍 - 若必须用
apply(比如调用外部 API、复杂状态机),才考虑加速方案 -
apply返回类型不一致时(例如有时返回str,有时返回None),pandas 会降级为objectdtype,后续操作更慢
swifter 不是银弹:自动切换的边界在哪?
swifter 本质是给 apply 包了一层“智能路由”:小数据走原生 apply,大数据试运行后切到 Dask 或 modin 后端。但它不会帮你改逻辑,且默认行为容易误判。
- 安装后直接替换
df.apply(...)→df.swifter.apply(...)即可,但首次运行会预热、采样,可能比原生还慢一点 - 对
axis=1场景效果最明显;axis=0(列方向)加速有限,因 pandas 列操作本就较优 - 默认启用
allow_dask_on_strings=True,但若你的字符串列含大量NaN,Dask 可能报TypeError: expected bytes, got float,此时要显式关掉:df.swifter.allow_dask_on_strings(False).apply(...) - 它不支持
apply的result_type参数,若需强制统一返回类型(如全转float64),得在函数内部处理
自己上多进程:什么时候该扔掉 swifter?
当你需要稳定可控的并行、或 swifter 报错/不生效时,直接用 multiprocessing.Pool 或 concurrent.futures.ProcessPoolExecutor 更可靠。注意:不能直接传整个 DataFrame 给子进程——序列化开销大,且 pandas 对象跨进程共享困难。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 推荐按行切片分块:
np.array_split(df, os.cpu_count()),再用pool.map分发每块 - 函数必须可被 pickle(不能是 lambda、嵌套函数、类方法),且所有依赖(如自定义模块)需在子进程里重新 import
- 避免在子进程中调用
df.apply—— 这等于套娃慢,应把原始函数抽出来单独定义,直接作用于Series或dict - 示例片段:
def process_chunk(chunk): return chunk['col_a'].str.upper() + '_' + chunk['col_b'].astype(str)
with ProcessPoolExecutor() as executor: chunks = np.array_split(df, 4) results = list(executor.map(process_chunk, chunks)) df_result = pd.concat(results, ignore_index=True)
容易被忽略的「假加速」陷阱
很多人测速时只看 apply 行耗时,却漏掉前后链路。比如:用 swifter 加速了 apply,但上游做了 df.groupby(...).apply(...) —— 此时 swifter 根本不生效,因为 groupby.apply 是另一套实现。
-
swifter只包装了DataFrame.apply和Series.apply,对groupby、rolling、resample等对象的apply无效 - 多进程下内存暴涨常见:每个子进程都加载一份完整 DataFrame 副本(即使只读),10GB 数据 + 8 进程 ≈ 80GB 内存占用
- Windows 上
spawn启动方式导致子进程重复导入模块,若模块里有顶层计算或日志初始化,会拖慢启动;Linux/macOS 的fork轻量得多
事情说清了就结束。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










