高效使用Pandas:提升数据处理速度的七个技巧
Pandas 是 Python 的默认数据操作库。但如果你使用不当,只会给自己增加不必要的工作量。你见过有人逐行遍历 DataFrame 吗?简直是一种折磨,就像看到有人用牙刷洗车一样。
Pandas 很快,但前提是你知道如何使用它。问题是,大多数人并不了解。他们把它当作一个缓慢、笨重的电子表格,而不是一个优化的强大工具。他们本不应该使用循环的时候用了循环,误用函数,然后在数据集增长到数万行时,性能问题就出现了。
现实是:Pandas 构建在 NumPy 之上,而 NumPy 针对向量化操作进行了优化。也就是说,尽可能对整列进行操作,而不是逐行循环。然而,许多开发者本能地使用循环,因为这正是他们所习惯的。旧习惯难改。但在 Pandas 中,循环几乎总是最慢的方式。
不过,性能并不是唯一的问题。代码的可读性也很重要。如果你的 Pandas 代码看起来像是 .loc[]、.iloc[]、.apply() 和无尽条件语句的混乱组合,那么你不仅会让自己感到沮丧,也会让其他阅读你代码的人感到困惑。干净、高效的 Pandas 代码不仅仅是速度快,更是要让代码一目了然。
好消息是:Pandas 有一些内置的快捷方式,可以加速、简化操作,并减少挫败感。其中一些非常简单,比如使用向量化操作而不是循环。还有一些,比如 query() 或 merge(),只需要稍微改变一下思维方式,就能节省大量的精力。一些技巧甚至可以帮助减少内存使用,这在处理大型数据集时尤为重要。
这些不是“知道更好”的技巧,而是写出高效 Pandas 代码与写出普通代码的区别。如果你在处理金融数据、清理脏乱的 CSV 文件或处理数十万行数据,这七个技巧将为你的工作流程节省宝贵的时间。
前提条件
在开始之前,请确保你具备以下条件:
对 Python 和 Pandas 有基本了解一个可用的 Python 环境(Jupyter、VS Code,无论你偏好哪种)一些示例数据(CSV 文件、SQL 导出文件,任何可以练习的数据)已安装 Pandas(如果尚未安装,请运行 pip install pandas)
1. 停止使用循环——改用向量化操作
问题 循环很慢。如果你逐行遍历 DataFrame,那你就做错了。
为什么重要 Pandas 构建在 NumPy 之上,而 NumPy 针对快速的向量化操作进行了优化。这意味着你可以一次性对整个列进行计算,而不是使用循环。这种方式更快且更简洁。
解决方法 不要这样写:
import pandas as pd
df = pd.DataFrame({'a': range(1, 6), 'b': range(10, 15)})
df['c'] = [x * y for x, y in zip(df['a'], df['b'])]
要这样写:
df['c'] = df['a'] * df['b']
更快、更干净,且没有不必要的循环。
避免这个错误 .iterrows() 看起来是个好主意,但其实很慢。使用向量化操作或 .apply()(但仅在需要时使用,见技巧 #7)。
2. 使用 query() 更快地过滤数据
问题 使用布尔条件过滤数据很快就会变得复杂。
解决方法 不要这样写:
df[(df['a'] > 2) & (df['b'] < 14)]
要这样写:
df.query('a > 2 and b < 14')
更易读,且运行速度更快。
专业提示 如果需要在 .query() 中使用变量,请使用 @:
threshold = 2
df.query('a > @threshold')
3. 使用 astype() 节省内存
问题 大型 DataFrame 会消耗大量内存。
解决方法 尽可能降级数据类型:
df['a'] = df['a'].astype('int8')
使用以下命令检查内存使用情况:
df.info()
注意 降级浮点数可能会导致精度损失。除非需要 float64,否则请使用 float32。
4. 轻松处理缺失数据
问题 NaN 值会破坏计算。
解决方法
删除它们:df.dropna()填充它们:df.fillna(0)插值:df.interpolate()
专业提示 插值在处理时间序列数据时非常有用。
5. 使用 groupby() 更高效地处理数据
问题 手动汇总数据是浪费时间。
解决方法 使用 groupby() 快速聚合数据:
df.groupby('category')['sales'].sum()
需要多重聚合?使用 .agg():
df.groupby('category').agg({'sales': ['sum', 'mean']})
你知道吗? 你还可以使用 transform() 将聚合值添加回原始 DataFrame,而不会丢失原始行结构:
df['total_sales'] = df.groupby('category')['sales'].transform('sum')
6. 合并 DataFrame 而不拖慢代码
问题 不当的连接操作会拖慢一切。
解决方法 正确使用 merge():
df_merged = df1.merge(df2, on='id', how='inner')
最佳实践 如果要保留第一个 DataFrame 中的所有记录,请使用 how='left'。
性能提示 对于大型 DataFrame,确保连接键已索引以加快合并速度:
df1.set_index('id', inplace=True)
df2.set_index('id', inplace=True)
df_merged = df1.join(df2, how='inner')
7. 正确使用 .apply()(并避免过度使用)
问题 .apply() 功能强大,但经常被误用。
解决方法 将其用于复杂的逐行操作:
df['new_col'] = df['a'].apply(lambda x: x**2 if x > 2 else x)
但如果只是修改单列,请改用 .map(),它更快。
避免这个错误 不要在使用向量化操作可以完成任务时使用 .apply()。.apply() 比 Pandas 内置函数慢。
最后总结 这些技巧可以让你的 Pandas 工作流程更加顺畅、快速且易于阅读。不再有不必要的循环,不再有缓慢的连接,只有干净、高效的代码。
在你的下一个项目中试试这些技巧。如果你想进一步探索,请查看官方 Pandas 文档。
下一步建议:
在你的数据集上尝试这些技巧学习 Pandas 中的多级索引,以实现更强大的数据操作如果你处理的数据集太大,无法放入内存,可以探索 Dask
参考资料:
官方 Pandas 文档:pandas documentation — pandas 2.2.3 documentationJake VanderPlas 的《Python 数据科学手册》:Python Data Science Handbook | Python Data Science HandbookNumPy 文档:NumPy documentation — NumPy v2.2 Manual高效 Pandas:性能优化的最佳实践:Fast, Flexible, Easy and Intuitive: How to Speed Up Your pandas Projects – Real PythonWes McKinney 的 Pandas 性能提示:https://wesmckinney.com/blog/Dask 用于并行计算与 Pandas:Dask DataFrame — Dask documentation