跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

Python中Pandas如何高效循环处理_尽量使用向量化运算替代for循环

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

相关文章