Pandas 是 Python 生态中最受欢迎的数据分析库之一,广泛应用于数据清洗、转换、聚合和可视化。然而,当数据量增长到数百万甚至上千万行时,Pandas 可能会变得缓慢,消耗大量内存,甚至导致程序崩溃。

本文将深入探讨 Pandas 性能优化的关键策略,涵盖数据类型优化、向量化计算、内存管理、高效查询技巧、IO 优化以及替代方案(如 Dask 和 Modin)。无论你是数据分析师、数据科学家还是 Python 开发者,这些优化技巧都能显著提升你的数据处理效率。

1. 选择高效的数据类型

Pandas 默认使用较宽的数据类型(如 int64float64),但许多场景下可以改用更节省内存的类型。

1.1 使用 category 类型优化字符串列

如果某列的取值是有限的(如性别、国家、产品类别),可以转换为 category 类型:

df['category_column'] = df['category_column'].astype('category')

优化效果

  • 内存占用减少 5~10 倍

  • 分组 (groupby) 和排序 (sort_values) 速度更快

1.2 使用更小的数值类型

  • int8(-128 到 127)

  • int16(-32,768 到 32,767)

  • float32(节省 50% 内存)

df['small_int'] = df['large_int'].astype('int16')
df['float_col'] = df['float_col'].astype('float32')

1.3 避免 object 类型

object 类型存储的是 Python 对象的指针,效率极低。尽量使用:

  • category(分类数据)

  • datetime64(日期时间)

  • int/float(数值数据)

2. 避免循环,使用向量化操作

Python 循环在 Pandas 中非常慢,应尽量使用 向量化操作(NumPy/Pandas 内置函数)。

2.1 避免 iterrows() 和 itertuples()

# ❌ 慢 - 逐行循环
for index, row in df.iterrows():
    df.loc[index, 'new_col'] = row['col1'] * 2

# ✅ 快 - 向量化计算
df['new_col'] = df['col1'] * 2

2.2 使用 apply() 时选择 axis=1 谨慎

apply(axis=1) 仍然是逐行操作,比向量化慢 100 倍以上:

# ❌ 慢
df['new_col'] = df.apply(lambda row: row['col1'] + row['col2'], axis=1)

# ✅ 快
df['new_col'] = df['col1'] + df['col2']

2.3 使用 eval() 加速复杂表达式

# 比传统方法快 2~3 倍
df.eval('result = (col1 + col2) / col3', inplace=True)

3. 高效查询和索引优化

3.1 使用 query() 替代布尔索引

# ❌ 较慢
filtered_df = df[(df['col1'] > 100) & (df['col2'] < 50)]

# ✅ 更快
filtered_df = df.query('col1 > 100 & col2 < 50')

3.2 使用 isin() 替代多个 OR 条件

# ❌ 慢
df_filtered = df[(df['id'] == 1) | (df['id'] == 2) | (df['id'] == 3)]

# ✅ 快
valid_ids = [1, 2, 3]
df_filtered = df[df['id'].isin(valid_ids)]

3.3 设置索引加速查询

df = df.set_index('timestamp_column')  # 加速时间范围查询
df.loc['2023-01-01':'2023-01-31']    # 比布尔过滤快 10 倍

4. 内存优化技巧

4.1 减少 DataFrame 副本

  • 使用 inplace=True 避免创建副本:

    df.drop(columns=['unused_col'], inplace=True)  # 比 `df = df.drop(...)` 更省内存
  • 使用 copy=False 在必要时才复制数据:

    new_df = df[['col1', 'col2']].copy()  # 避免视图问题

4.2 手动释放内存

import gc
del large_df  # 删除不再使用的 DataFrame
gc.collect()  # 强制垃圾回收

5. IO 优化:更快地读写数据

5.1 使用 Parquet/Feather 替代 CSV

  • CSV 是文本格式,读写慢。

  • Parquet(列式存储)和 Feather(二进制)快 10 倍:

    df.to_parquet('data.parquet')       # 最佳选择(支持压缩)
    df.to_feather('data.feather')       # 极快,但不支持压缩

 5.2 使用 chunksize 处理大文件

chunk_size = 100_000
for chunk in pd.read_csv('huge_file.csv', chunksize=chunk_size):
    process(chunk)  # 逐块处理,避免内存不足

5.3 只读取需要的列

cols = ['col1', 'col2']  # 仅加载必要的列
df = pd.read_csv('data.csv', usecols=cols)

6. 替代方案:超越 Pandas 的性能极限

如果数据超过 1GB,Pandas 可能仍然较慢,可考虑:

6.1 Dask(并行计算)

import dask.dataframe as dd
ddf = dd.read_csv('huge_data_*.csv')  # 支持多文件并行读取
result = ddf.groupby('category').mean().compute()  # 延迟计算

6.2 Modin(Pandas 的并行替代品)

import modin.pandas as mpd
df = mpd.read_csv('big_data.csv')  # 自动并行化操作

6.3 Polars(Rust 高性能 DataFrame)

import polars as pl
df = pl.read_csv('data.csv')  # 比 Pandas 快 5~10 倍

7. 总结:Pandas 优化清单

优化方向 具体方法
数据类型 使用 categoryint32/float32
避免循环 使用向量化操作,避免 iterrows()
查询优化 用 query()isin()、设置索引
内存管理 减少副本,手动 del + gc.collect()
IO 优化 用 Parquet/Feather,chunksize 分块读取
大数据方案 Dask、Modin、Polars

结论

Pandas 性能优化是一个系统工程,涉及 数据类型选择、向量化计算、查询优化、内存管理和 IO 加速。对于超大数据集,可以结合 Dask、Modin 或 Polars 进一步提升性能。

通过本文的技巧,你可以让 Pandas 处理 百万级数据快 10 倍,千万级数据仍然流畅运行

 

Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐