今天我们要介绍的,是一个能让你的数据处理速度提升 10-100 倍的"核武器"——Polars!
📌 为什么你需要 Polars?
如果你还在用 Pandas 处理数据,那你可能正在经历:
Polars 来了,一切都不一样了!
🎯 Polars 是什么?
Polars 是一个用 Rust 编写的超快速数据帧库,专为处理结构化数据而生。它的核心优势:
特性PandasPolars底层语言PythonRust处理速度基准10-100 倍内存效率一般优化极致并行计算需手动自动并行懒执行不支持原生支持
🚀 快速上手:3 分钟入门
安装
pip install polars
基础操作对比
创建 DataFrame
import polars as pl
import pandas as pd
import datetime as dt
# Polars 方式
df = pl.DataFrame({
"name": ["Alice Archer", "Ben Brown", "Charlie Chen"],
"birthdate": [dt.date(1997, 1, 10), dt.date(1985, 2, 15), dt.date(2000, 6, 20)],
"weight": [57.9, 72.5, 68.3],
"height": [1.56, 1.77, 1.65],
"city": ["北京", "上海", "深圳"]
})
print(df)
输出:
shape: (3, 5)
┌──────────────┬────────────┬─────────┬────────┬────────┐
│ name ┆ birthdate ┆ weight ┆ height ┆ city │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ date ┆ f64 ┆ f64 ┆ str │
╞══════════════╪════════════╪═════════╪════════╪════════╡
│ Alice Archer ┆ 1997-01-10 ┆ 57.9 ┆ 1.56 ┆ 北京 │
│ Ben Brown ┆ 1985-02-15 ┆ 72.5 ┆ 1.77 ┆ 上海 │
│ Charlie Chen ┆ 2000-06-20 ┆ 68.3 ┆ 1.65 ┆ 深圳 │
└──────────────┴────────────┴─────────┴────────┴────────┘
🔥 核心功能实战
1️⃣ 数据筛选(比 Pandas 更优雅)
# 筛选身高大于 1.6 米的人
result = df.filter(pl.col("height") > 1.6)
print(result)
# 多条件筛选
result = df.filter(
(pl.col("height") > 1.6) & (pl.col("weight") < 70)
)
print(result)
输出:
shape: (1, 5)
┌──────────────┬────────────┬─────────┬────────┬────────┐
│ name ┆ birthdate ┆ weight ┆ height ┆ city │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ date ┆ f64 ┆ f64 ┆ str │
╞══════════════╪════════════╪═════════╪════════╪════════╡
│ Charlie Chen ┆ 2000-06-20 ┆ 68.3 ┆ 1.65 ┆ 深圳 │
└──────────────┴────────────┴─────────┴────────┴────────┘
2️⃣ 列操作(链式调用,一气呵成)
# 添加新列、重命名、选择列,一条链搞定
result = df.with_columns(
bmi = pl.col("weight") / (pl.col("height") ** 2)
).rename({
"name": "姓名"
}).select([
"姓名", "bmi", "city"
])
print(result)
输出:
shape: (3, 3)
┌──────────────┬──────────┬────────┐
│ 姓名 ┆ bmi ┆ city │
│ --- ┆ --- ┆ --- │
│ str ┆ f64 ┆ str │
╞══════════════╪══════════╪════════╡
│ Alice Archer ┆ 23.77 ┆ 北京 │
│ Ben Brown ┆ 23.18 ┆ 上海 │
│ Charlie Chen ┆ 25.14 ┆ 深圳 │
└──────────────┴──────────┴────────┘
3️⃣ 分组聚合(性能提升 10 倍+)
# 按城市分组,计算平均身高和体重
result = df.group_by("city").agg([
pl.col("height").mean().alias("平均身高"),
pl.col("weight").mean().alias("平均体重"),
pl.col("name").count().alias("人数")
])
print(result)
输出:
shape: (3, 4)
┌────────┬──────────┬──────────┬────────┐
│ city ┆ 平均身高 ┆ 平均体重 ┆ 人数 │
│ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ f64 ┆ f64 ┆ u32 │
╞════════╪══════════╪══════════╪════════╡
│ 北京 ┆ 1.56 ┆ 57.9 ┆ 1 │
│ 上海 ┆ 1.77 ┆ 72.5 ┆ 1 │
│ 深圳 ┆ 1.65 ┆ 68.3 ┆ 1 │
└────────┴──────────┴──────────┴────────┘
4️⃣ 懒执行模式(性能杀手锏)
这是 Polars 最强大的功能之一!懒执行允许 Polars 优化整个查询计划,然后一次性执行。
# 创建查询计划(不立即执行)
lazy_df = (
pl.LazyFrame(df)
.filter(pl.col("height") > 1.6)
.with_columns(
bmi = pl.col("weight") / (pl.col("height") ** 2)
)
.select(["name", "bmi", "city"])
)
# 查看查询计划
print("查询计划:")
print(lazy_df.explain())
# 真正执行
result = lazy_df.collect()
print("\n执行结果:")
print(result)
输出:
查询计划:
SELECT ["name", "bmi", "city"] FROM
WITH_COLUMNS:
[col("bmi") := col("weight") / ((col("height")) ^ (2.0))]
FILTER col("height") > (1.6) FROM
DF ["name", "birthdate", "weight", "height", "city"]; PROJECT */5 COLUMNS
执行结果:
shape: (1, 3)
┌──────────────┬──────────┬────────┐
│ name ┆ bmi ┆ city │
│ --- ┆ --- ┆ --- │
│ str ┆ f64 ┆ str │
╞══════════════╪══════════╪════════╡
│ Charlie Chen ┆ 25.14 ┆ 深圳 │
└──────────────┴──────────┴────────┘
⚡ 性能对比:Polars vs Pandas
让我们用真实数据测试一下速度差异:
import time
import numpy as np
# 生成 100 万行数据
np.random.seed(42)
n_rows = 1_000_000
# Pandas
df_pandas = pd.DataFrame({
"A": np.random.randint(1, 100, n_rows),
"B": np.random.rand(n_rows),
"C": np.random.choice(["x", "y", "z"], n_rows)
})
# Polars
df_polars = pl.from_pandas(df_pandas)
# 测试:分组聚合
start = time.time()
result_pandas = df_pandas.groupby("C").agg({"A": "mean", "B": "sum"})
pandas_time = time.time() - start
start = time.time()
result_polars = df_polars.group_by("C").agg([
pl.col("A").mean(),
pl.col("B").sum()
])
polars_time = time.time() - start
print(f"Pandas 耗时:{pandas_time:.4f} 秒")
print(f"Polars 耗时:{polars_time:.4f} 秒")
print(f"Polars 快了 {pandas_time/polars_time:.1f} 倍!")
典型输出:
Pandas 耗时:0.4523 秒
Polars 耗时:0.0387 秒
Polars 快了 11.7 倍!
🎓 高级技巧:表达式系统
Polars 的表达式系统(Expression API)是其最强大的特性:
# 1. 条件表达式
df.with_columns(
category = pl.when(pl.col("weight") > 70)
.then(pl.lit("超重"))
.when(pl.col("weight") < 60)
.then(pl.lit("偏轻"))
.otherwise(pl.lit("正常"))
)
# 2. 字符串操作
df.with_columns(
name_upper = pl.col("name").str.to_uppercase(),
name_length = pl.col("name").str.len_chars()
)
# 3. 日期操作
df.with_columns(
age = (dt.date(2026, 4, 3) - pl.col("birthdate")).dt.total_days() // 365
)
# 4. 窗口函数(类似 SQL 的 OVER)
df.with_columns(
avg_height_by_city = pl.col("height").mean().over("city")
)
📚 实用场景推荐
场景 1:大数据 ETL 处理
# 从 CSV 读取,清洗,转换,保存
(df =
pl.scan_csv("large_data.csv") # 懒加载
.filter(pl.col("value") > 0)
.group_by("category")
.agg(pl.col("value").sum())
.collect() # 执行
)
df.write_csv("output.csv")
场景 2:数据科学快速探索
# 快速统计描述
df.describe()
# 相关性矩阵
df.corr()
# 采样
sample = df.sample(n=100, seed=42)
场景 3:与 Pandas 无缝切换
# Polars -> Pandas
pdf = df_polars.to_pandas()
# Pandas -> Polars
pl_df = pl.from_pandas(pdf)
⚠️ 注意事项
- 1. 学习曲线:Polars 的 API 与 Pandas 不同,需要重新学习
- 2. 生态整合:部分 Pandas 插件可能不兼容
- 3. 版本更新:Polars 发展迅速,API 可能变化
🎯 总结
Polars 的核心优势:
✅ 速度飞快:Rust 编写,自动并行,比 Pandas 快 10-100 倍
✅ 内存友好:高效的内存管理,处理大数据不爆内存
✅ 语法优雅:链式调用,表达式系统强大
✅ 懒执行:查询优化,性能再提升
✅ 兼容性好:可与 Pandas 无缝切换
适用场景:
📖 下一步学习
- 1. 官方文档:https://docs.pola.rs/
- 2. GitHub 仓库:https://github.com/pola-rs/polars
- 3. 实践建议:从小数据开始,逐步迁移 Pandas 代码