详解 DataFrame 高性能处理工具 – Polars
Polars
是一个现代化的、高性能的 DataFrame 库,旨在为大规模数据处理提供极快的性能。它是用 Rust 编写的,并且专注于并行处理和内存效率。相比于 pandas
,Polars
在处理大规模数据时可以更高效,尤其在处理多核处理器和大内存的环境下,性能优势更加明显。
1. Polars 简介
- 目标:Polars 旨在为数据科学家、分析师、工程师等提供一个既高效又易于使用的数据处理库,特别是对于需要处理大量数据的应用场景。
- 语言支持:Polars 支持 Python、Rust、Node.js 等多种语言。
- 架构:基于 Rust 的多线程并行计算,使用 Arrow 库作为数据存储格式,从而提高内存效率和计算性能。
- 特点:
- 高性能:Polars 是用 Rust 编写的,Rust 是一门以性能为重点的系统编程语言,Polars 的核心依靠 Rust 的零成本抽象、并行处理和内存管理优势。
- 易用性:API 设计灵感来源于
pandas
,容易上手,适合已有pandas
使用经验的用户。 - 延迟计算:Polars 支持延迟计算,计算图不会立即执行,直到你调用
.collect()
。 - 多线程并行处理:在多核 CPU 上,Polars 能够有效地并行处理数据,利用多核加速计算。
2. 安装 Polars
2.1 安装 Python 版本
Polars 在 Python 中提供了丰富的功能,可以通过 pip 安装:
pip install polars
2.2 安装 Rust 版本
Rust 版本的 Polars 可以通过 Cargo 进行安装:
cargo install polars
3. Polars 与 Pandas 对比
Polars 的设计是为了在高性能、大规模数据处理上超越 pandas
,特别是对于那些处理数百万、数十亿条数据的任务。
特性 | Pandas | Polars |
---|---|---|
语言 | Python(内核用 Cython) | Rust(绑定到 Python、Node.js 等) |
数据存储 | DataFrame 和 Series(基于 NumPy) | Arrow 数据格式(列式存储) |
并行处理 | 单线程 | 多线程并行处理,自动分配工作到多个核心 |
延迟计算 | 无 | 支持延迟计算,只有调用 .collect() 时才计算 |
内存效率 | 适中 | 内存更高效,减少内存复制和数据传输 |
操作速度 | 慢于 Polars | 更快,尤其在大数据集上,速度优势明显 |
4. Polars 核心概念
4.1 DataFrame 和 Series
- DataFrame:类似于
pandas
中的 DataFrame,是一个二维的表格结构,包含行和列。 - Series:类似于
pandas
中的 Series,是单一列的数据结构。
4.2 延迟计算(LazyFrame)
Polars 的延迟计算可以通过 LazyFrame
来实现。延迟计算可以将多个操作合并成一个优化过的查询,这样可以避免中间结果的计算,提高整体性能。只有在调用 .collect()
时,计算才会真正执行。
import polars as pl
# 延迟计算
lazy_df = pl.scan_csv('data.csv') # 延迟加载数据
result = lazy_df.filter(pl.col('age') > 30).select([pl.col('name'), pl.col('age')])
# 执行并收集结果
df = result.collect()
print(df)
4.3 多线程并行处理
Polars 利用多线程来加速计算,特别是对于 CPU 密集型的操作。Polars 会自动在多个 CPU 核心上并行执行任务,大幅提高数据处理的速度。
5. Polars 的基本用法
5.1 创建 DataFrame
你可以使用字典、列表、Numpy 数组等方式创建 DataFrame。
import polars as pl
# 从字典创建 DataFrame
df = pl.DataFrame({
'name': ['Alice', 'Bob', 'Charlie'],
'age': [25, 30, 35],
'city': ['New York', 'Los Angeles', 'Chicago']
})
print(df)
输出:
shape: (3, 3)
┌─────────┬─────┬────────────┐
│ name │ age │ city │
│ --- │ --- │ --- │
│ str │ i64 │ str │
├─────────┼─────┼────────────┤
│ Alice │ 25 │ New York │
│ Bob │ 30 │ Los Angeles│
│ Charlie │ 35 │ Chicago │
└─────────┴─────┴────────────┘
5.2 数据选择和过滤
与 pandas
相似,Polars 支持通过列名选择和过滤数据。
# 选择单列
print(df['name'])
# 多列选择
df_filtered = df.select(['name', 'city'])
print(df_filtered)
# 过滤数据
df_age_filtered = df.filter(pl.col('age') > 30)
print(df_age_filtered)
5.3 基本聚合操作
Polars 支持基本的聚合操作,如 groupby
、sum
、mean
、count
等。
# 按 city 分组并计算 age 的平均值
df_grouped = df.groupby('city').agg([pl.col('age').mean().alias('avg_age')])
print(df_grouped)
5.4 使用延迟计算(LazyFrame)
延迟计算对于大数据集的处理非常有用。通过 scan_*
方法,Polars 提供了延迟计算的功能。
lazy_df = pl.scan_csv('data.csv')
result = lazy_df.filter(pl.col('age') > 30).select(['name', 'age'])
df_result = result.collect() # 执行并收集结果
print(df_result)
6. Polars 高级功能
6.1 数据连接(Join)
Polars 提供了多种连接方式(如内连接、外连接等),用于将不同的 DataFrame 合并。
df1 = pl.DataFrame({
'id': [1, 2, 3],
'name': ['Alice', 'Bob', 'Charlie']
})
df2 = pl.DataFrame({
'id': [1, 2, 4],
'age': [25, 30, 35]
})
# 内连接
df_joined = df1.join(df2, on='id', how='inner')
print(df_joined)
6.2 支持多种文件格式
Polars 支持多种文件格式的读取和写入,包括 CSV、JSON、Parquet 等。
# 读取 CSV
df = pl.read_csv('data.csv')
# 写入 Parquet
df.write_parquet('output.parquet')
6.3 数据类型转换
Polars 支持多种数据类型转换功能,例如将字符串列转换为日期时间类型:
df = pl.DataFrame({
'date': ['2021-01-01', '2022-02-02', '2023-03-03']
})
df = df.with_columns(pl.col('date').str.strptime(pl.Date, fmt='%Y-%m-%d'))
print(df)
7. Polars 性能优势
7.1 性能优化
Polars 依赖 Rust 和 Arrow 技术栈,这使得它在性能上远超 Python 的 pandas
,尤其在大规模数据集上,Polars 的性能表现十分出色。Polars 内部使用列式存储格式(Arrow),能够高效地处理列操作。
7.2 多核并行
Polars 在多核机器上表现尤为突出,能够自动并行化数据处理任务,充分利用现代 CPU 的多核优势。
7.3 低内存消耗
Polars 使用内存池(memory pool)和零复制技术,使得它的内存消耗非常低。尤其是在需要处理大数据集时,Polars 可以显著减少内存占用。
8. 总结
Polars 是一个功能强大、高性能的数据处理库,特别适合于处理大规模数据集。与 pandas
相比,Polars 在性能和内存效率方面具有显著的优势,尤其在大数据和并行计算场景下表现出色。它提供了类似
pandas
的 API,易于上手,并支持延迟计算、多线程和多种文件格式的读写。如果你处理的数据量非常大或需要更快的性能,Polars 是一个值得考虑的替代方案。
发表回复