Python Polars 高性能数据处理实战:替代 Pandas 的极速数据分析利器

2026-06-06 0 911

在数据科学领域,Pandas 长期占据着核心地位,但随着数据集规模不断膨胀,其单核执行和内存消耗的瓶颈日益明显。近年来,一个基于 Rust 内核的 Python Polars 库迅速崛起,凭借惰性计算、向量化执行和零拷贝内存管理,在处理数百万行乃至数亿行数据时展现出数十倍的性能优势。本文将带你从零开始掌握 Polars,通过完整的实战案例,完成从 Pandas 到 Polars 的高效迁移。

一、Polars 的核心优势

Polars 被设计为一个真正并行化的 DataFrame 库,与 Pandas 的根本区别在于:

  • Apache Arrow 内存模型:数据以列式格式存储,支持零拷贝共享,减少序列化开销。
  • 惰性执行:构建查询计划而非立即执行,优化器自动合并操作,减少中间结果内存分配。
  • 全核并行:几乎所有操作都利用多线程,充分利用现代 CPU。
  • 表达式系统:使用链式表达式而非隐式索引,代码更加清晰且不易出错。

这些特性使得 Polars 在数据清洗、特征工程、日志分析等场景下,比 Pandas 快 5 到 50 倍,且内存占用更低。

二、安装与快速入门

使用 pip 安装 Polars:

pip install polars

同时推荐安装 pyarrow 以获得更好的文件读写支持。我们来创建一个简单的 DataFrame 并查看其结构:

import polars as pl

# 从字典创建 DataFrame
df = pl.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'Diana'],
    'age': [25, 30, 35, 40],
    'salary': [70000, 80000, 120000, 95000]
})

print(df)
# 输出:
# shape: (4, 3)
# ┌─────────┬─────┬────────┐
# │ name    ┆ age ┆ salary │
# │ ---     ┆ --- ┆ ---    │
# │ str     ┆ i64 ┆ i64    │
# ╞═════════╪═════╪════════╡
# │ Alice   ┆ 25  ┆ 70000  │
# │ Bob     ┆ 30  ┆ 80000  │
# │ Charlie ┆ 35  ┆ 120000 │
# │ Diana   ┆ 40  ┆ 95000  │
# └─────────┴─────┴────────┘

与 Pandas 不同,Polars 在打印时会显示列的类型(str, i64 等)和形状。这种清晰的类型展示对编写类型安全的查询非常有帮助。

三、核心操作:选择、过滤与排序

Polars 的操作基于表达式 pl.col(),避免了 Pandas 中常见的链式索引问题。我们用经典的 Titanic 数据集示范。

# 读取 CSV 文件(Polars 自动推断类型)
df = pl.read_csv('titanic.csv')
print(df.head())

# 选择若干列
df.select([
    pl.col('Survived'),
    pl.col('Pclass'),
    pl.col('Name')
])

# 过滤:找出票价大于100的乘客
df.filter(pl.col('Fare') > 100)

# 多条件过滤:一等舱且年龄小于18的乘客
df.filter((pl.col('Pclass') == 1) & (pl.col('Age') < 18))

# 排序:按年龄降序,缺失值放最后
df.sort('Age', descending=True, nulls_last=True)

表达式可以组合,并支持 is_not_null()is_in()str.contains() 等方法,覆盖绝大多数数据筛选需求。

四、数据清洗与列操作

Polars 的列操作通过 with_columns 添加或修改列,结合表达式可以完成复杂清洗。

# 添加新列:将票价转换为欧元(假设汇率0.93)
df_clean = df.with_columns(
    (pl.col('Fare') * 0.93).alias('Fare_EUR')
)

# 修改列类型:Age 转为浮点
df_clean = df_clean.with_columns(
    pl.col('Age').cast(pl.Float64)
)

# 填充缺失值:年龄用中位数填充,港口用'S'填充
df_filled = df.with_columns(
    pl.col('Age').fill_null(df['Age'].median()),
    pl.col('Embarked').fill_null('S')
)

# 字符串操作:提取姓氏(Name 中逗号前的部分)
df_names = df.with_columns(
    pl.col('Name').str.split(',').list.first().alias('Surname')
)

这些操作在执行时非常高效,因为每一个 with_columns 都是一次计划中的步骤,可以合并优化。

五、分组聚合与窗口函数

分组聚合是数据分析的核心。Polars 的 group_by 配合 agg 方法提供了丰富的聚合能力。

# 按船舱等级分组,计算生存率和平均票价
agg_df = df.group_by('Pclass').agg([
    pl.col('Survived').mean().alias('SurvivalRate'),
    pl.col('Fare').mean().alias('AvgFare'),
    pl.col('PassengerId').count().alias('Count')
])
print(agg_df)

窗口函数(Window Functions)允许在不破坏行数的前提下添加聚合列:

# 为每个乘客添加所在船舱等级的平均票价
df_with_avg = df.with_columns(
    pl.col('Fare').mean().over('Pclass').alias('AvgFareByClass')
)

更复杂的分组排序后取前N行也可以轻松实现:

# 每个船舱等级中票价最高的2名乘客
top_fare_per_class = df.sort('Fare', descending=True).group_by('Pclass').head(2)

六、惰性执行与查询优化

Polars 的杀手锏是惰性执行。使用 lazy() 方法将 DataFrame 转为 LazyFrame,后续操作构建查询计划,直到调用 collect() 才真正执行。优化器会自动调整操作顺序、合并过滤,极大减少内存分配。

# 惰性模式示例
lazy_df = df.lazy()

result = (lazy_df
    .filter(pl.col('Age') > 18)
    .group_by('Pclass')
    .agg(pl.col('Survived').mean().alias('AdultSurvival'))
    .sort('Pclass')
)

# 此时仍无实际计算,执行 collect() 触发
final = result.collect()
print(final)

使用 explain() 可以查看优化后的执行计划:

print(result.explain())  # 输出类似SQL的查询计划

对于百万行以上的数据集,惰性执行通常能将计算时间缩短一半甚至更多,且内存峰值显著下降。

七、与 Pandas 的性能对比实战

我们用一段代码生成 1000 万行数据,并分别用 Pandas 和 Polars 进行分组聚合,直观感受速度差距。

import numpy as np
import pandas as pd
import polars as pl
import time

# 生成测试数据:1000万行,4列
n = 10_000_000
np.random.seed(42)
data = {
    'category': np.random.choice(['A','B','C','D'], n),
    'value1': np.random.randn(n),
    'value2': np.random.randn(n),
    'value3': np.random.randn(n)
}

# Pandas 测试
pdf = pd.DataFrame(data)
start = time.time()
pdf.groupby('category').agg({'value1':'mean','value2':'sum','value3':'std'})
pandas_time = time.time() - start

# Polars 测试(惰性执行)
pl_df = pl.DataFrame(data).lazy()
start = time.time()
(pl_df.group_by('category')
 .agg([pl.col('value1').mean(),pl.col('value2').sum(),pl.col('value3').std()])
 .collect())
polars_time = time.time() - start

print(f"Pandas 耗时: {pandas_time:.3f}秒")
print(f"Polars 耗时: {polars_time:.3f}秒")
print(f"加速比: {pandas_time/polars_time:.1f}x")

典型输出:Pandas 需要 3.2 秒,Polars 仅需 0.2 秒,加速超过 15 倍。在多核服务器上,加速比甚至可达 30 倍以上。

八、从 Pandas 迁移的实用对照表

常见 Pandas 操作对应的 Polars 写法:

# 读取 CSV
# Pandas: pd.read_csv('file.csv')
# Polars: pl.read_csv('file.csv')

# 选取列
# Pandas: df[['col1','col2']]
# Polars: df.select(['col1','col2'])

# 过滤行
# Pandas: df[df['age'] > 30]
# Polars: df.filter(pl.col('age') > 30)

# 分组聚合
# Pandas: df.groupby('key').agg({'val':'mean'})
# Polars: df.group_by('key').agg(pl.col('val').mean())

# 排序
# Pandas: df.sort_values('col')
# Polars: df.sort('col')

# 添加列
# Pandas: df['new'] = df['a'] + df['b']
# Polars: df.with_columns((pl.col('a') + pl.col('b')).alias('new'))

尽管语法略有不同,但 Polars 的表达式系统更加一致,避免了 Pandas 中 lociloc、链式赋值等容易引发警告的陷阱。

九、文件读写与数据源连接

Polars 支持 CSV、JSON、Parquet、IPC、Delta Lake 等多种格式,并可直接从数据库、S3 等读取。以 Parquet 为例:

# 写入 Parquet(极高的压缩比和读取速度)
df.write_parquet('titanic.parquet', compression='zstd')

# 读取 Parquet
df_parquet = pl.read_parquet('titanic.parquet')

连接 MySQL 或 PostgreSQL 可通过 pl.read_database() 实现:

import polars as pl
conn_str = "postgresql://user:pass@localhost:5432/mydb"
df_db = pl.read_database("SELECT * FROM users", conn_str)

这使得 Polars 能够直接嵌入 ETL 管道,无需先导出为中间文件。

十、最佳实践与总结

  • 惰性优先:始终将 DataFrame 转为 LazyFrame 后再进行复杂操作,最后 collect()
  • 链式表达式:使用 selectwith_columnsfilter 等链式调用,保持代码可读性。
  • 列操作采用表达式:避免使用行级循环,充分利用列式并行。
  • 适当设置类型:在创建 DataFrame 时指定 schema,可进一步提升性能。
  • 与 Pandas 互通:通过 df.to_pandas()pl.from_pandas() 在两者间转换,便于逐步迁移。

Polars 不是要完全取代 Pandas,而是在大数据量和高性能场景下提供更优选择。随着其生态系统日益成熟(支持 GPU、流式数据等),掌握 Polars 已成为 Python 数据工程师的核心竞争力。将本文的实战案例应用到你的日常工作中,你会感受到数据处理速度的质变。

Python Polars 高性能数据处理实战:替代 Pandas 的极速数据分析利器
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

版权声明:
本站资源有的来自互联网收集整理,本站纯免费分享提供学习使用,如果侵犯了您的合法权益,请联系本站我们会及时删除。
本站资源仅供研究、学习交流之用,免费开源项目不代表完全可商用,若商业用途请先咨询开发企业能否商用,否则产生的一切后果将由下载用户自行承担。
原创板块未经允许不得转载,否则将追究法律责任。

淘吗网 python Python Polars 高性能数据处理实战:替代 Pandas 的极速数据分析利器 https://www.taomawang.com/server/python/2091.html

常见问题

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务