for循环遍历DataFrame慢是因为每次取值需索引查找、类型检查和对象封装,相当于在C数组上套Python解释器“厚外套”,万行以上性能差10–100倍;应优先用向量化操作如np.where、pd.cut、str.方法等替代。
为什么
循环遍历 DataFrame 很慢
因为
底层是 NumPy 数组,而 Python 的
循环每次取值都要触发索引查找、类型检查、对象封装,相当于在 C 速度的数组上套了一层 Python 解释器的“厚外套”。尤其当行数超万,性能差距可达 10–100 倍。
常见错误现象:
看起来直观,但
是
对象,每轮都新建;
在循环里反复调用也一样慢。
别用
做数值计算或条件赋值
避免在循环里调用
或
查单行
如果必须逐行逻辑(比如调用外部 API),优先用
,它返回命名元组,开销低得多
不是万能解药:什么时候该用、什么时候该换
表面看是“向量化接口”,实际默认 axis=0 是按列调用函数,axis=1 才是按行——但后者几乎和
一样慢,因为它内部仍是 Python 循环 + 构造
。
使用场景判断:
立即学习
“
Python免费学习笔记(深入)
”;
纯列运算(如
)→ 可以,但不如直接
多列参与的简单逻辑(如
)→ 改用
需要 if-else 分支 → 优先用
或
,不是
性能影响:
在 10 万行数据上可能比等效向量化慢 50 倍以上。
Python 3.14.3
微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。
下载
替代
循环的真正向量化写法
核心原则:把操作从“对每个元素做判断/计算”转为“对整个数组批量运算”。Pandas 和 NumPy 提供了足够多的原语。
条件赋值不用
+
:用
分段逻辑不用循环判断:用
字符串处理:用
而非
时间运算:用
,不是循环加 datetime 对象
参数差异注意:
的三个参数必须长度一致或可广播;
方法默认跳过 NaN,而
需手动处理。
实在绕不开循环时的最小代价方案
比如要调用不能向量化的第三方函数、或逻辑依赖前一行结果(如累计状态机),这时得接受循环,但可以压低开销。
用
替代
:返回 tuple,访问字段用下标(
)比属性名(
)快 2–3 倍
提前提取 Series 为 NumPy 数组:
,在循环里直接操作
避免在循环内做
:先建空列表
,循环中
,最后一次性
容易被忽略的是:哪怕只循环 1 万次,如果每次调用一个含日志、数据库连接或正则编译的函数,瓶颈根本不在 Pandas —— 这时候该优化的是那个函数本身,不是循环写法。
forDataFrameforfor idx, row in df.iterrows():rowSeriesdf.iloc[i]iterrows()df.loc[]df.iloc[]itertuples()apply()apply()iterrows()Seriesdf['x'].apply(np.log)np.log(df['x'])df.apply(lambda r: r.a + r.b * 2, axis=1)df['a'] + df['b'] * 2np.where()pd.cut()apply()apply(axis=1)forforifnp.where(df['age'] > 30, 'adult', 'young')pd.cut(df['score'], bins=[0,60,80,100], labels=['F','C','A'])df['name'].str.upper()apply(str.upper)df['date'] + pd.Timedelta('7D')np.where()str.apply()itertuples(index=False, name=None)iterrows()row[0]row.aarr_a = df['a'].values; arr_b = df['b'].valuesarr_a[i]df.loc[i, 'c'] = ...results = []append()df['c'] = results