跳到主要内容

Polars 与大数据量处理

问题

Pandas 处理大数据量时很慢怎么办?Polars 是什么?和 Pandas 有什么区别?

答案

当数据量超过 百万行 级别,Pandas 的性能瓶颈会越来越明显。Polars 是用 Rust 编写的高性能 DataFrame 库,被视为 Pandas 的现代替代方案。

Polars vs Pandas 对比

对比PandasPolars
语言C/PythonRust
性能基线5~20 倍
内存较高更低(列式+压缩)
并行单线程自动多线程
惰性执行✅(LazyFrame)
API 风格命令式表达式(声明式)
生态极丰富快速增长
学习成本中(新 API)
面试建议

Polars 在数据分析面试中还不是必考项,但提到大数据量优化时能说出 Polars 是加分项。

Polars 基础操作

Polars 快速入门
import polars as pl

# 创建 DataFrame
df = pl.DataFrame({
'name': ['Alice', 'Bob', 'Charlie'],
'age': [25, 30, 35],
'salary': [15000, 20000, 25000]
})

# 读取 CSV / Parquet
df = pl.read_csv('data.csv')
df = pl.read_parquet('data.parquet')

# 选择列
df.select('name', 'age')
df.select(pl.col('name'), pl.col('age'))

# 筛选行
df.filter(pl.col('age') > 25)
df.filter((pl.col('age') > 25) & (pl.col('salary') > 18000))

# 新增列
df.with_columns(
(pl.col('salary') * 0.1).alias('bonus'),
pl.col('name').str.to_lowercase().alias('name_lower')
)

# 聚合
df.group_by('name').agg(
pl.col('salary').mean().alias('avg_salary'),
pl.col('age').max().alias('max_age')
)

# 排序
df.sort('salary', descending=True)

LazyFrame — 惰性执行

Polars 最强大的特性——查询计划优化:

LazyFrame(惰性执行)
# Eager 模式(立即执行)
result = df.filter(pl.col('age') > 25).select('name', 'salary')

# Lazy 模式(延迟执行,自动优化)
result = (
df.lazy() # 转为 LazyFrame
.filter(pl.col('age') > 25) # 不立即执行
.select('name', 'salary') # 不立即执行
.collect() # 触发执行 + 查询优化
)

# scan 直接以 Lazy 模式读取文件(最佳实践)
result = (
pl.scan_csv('data.csv') # 不读入全部数据
.filter(pl.col('city') == '北京') # 谓词下推:读取时就过滤
.select('name', 'salary') # 投影下推:只读需要的列
.collect()
)
LazyFrame 的优化
  • 谓词下推:过滤条件尽早执行,减少处理的数据量
  • 投影下推:只读取需要的列
  • 公共子表达式消除:避免重复计算
  • 并行执行:自动利用多核 CPU

Pandas → Polars 常用操作对照

操作PandasPolars
选列df[['a', 'b']]df.select('a', 'b')
筛选df[df['a'] > 1]df.filter(pl.col('a') > 1)
新增列df['c'] = df['a'] * 2df.with_columns((pl.col('a') * 2).alias('c'))
分组聚合df.groupby('a').agg({'b': 'mean'})df.group_by('a').agg(pl.col('b').mean())
排序df.sort_values('a')df.sort('a')
合并pd.merge(df1, df2, on='key')df1.join(df2, on='key')
去重df.drop_duplicates()df.unique()

大数据量处理策略

当 Pandas 不够快时,按数据规模选择方案:

数据规模推荐方案
< 100 万行Pandas 直接处理
100 万 ~ 1000 万行Pandas 优化 / Polars
1000 万 ~ 1 亿行Polars LazyFrame
> 1 亿行Spark / Hive / 数据库

Pandas 大数据优化技巧

Pandas 处理大数据量的优化
import pandas as pd

# 1. 使用 Parquet 而非 CSV(快 5~10 倍)
df = pd.read_parquet('data.parquet')

# 2. 只读需要的列
df = pd.read_csv('data.csv', usecols=['col1', 'col2'])

# 3. 指定数据类型减少内存
df = pd.read_csv('data.csv', dtype={
'id': 'int32', # int64 → int32
'price': 'float32', # float64 → float32
'city': 'category' # str → category
})

# 4. 分块读取
chunks = pd.read_csv('big.csv', chunksize=500000)
results = []
for chunk in chunks:
processed = chunk[chunk['amount'] > 0].groupby('city')['amount'].sum()
results.append(processed)
final = pd.concat(results).groupby(level=0).sum()

常见面试问题

Q1: 什么时候用 Polars 替代 Pandas?

答案

  • 数据量 > 百万行,Pandas 明显变慢
  • 需要自动多线程并行
  • 内存受限(Polars 更省内存)
  • 即使数据量不大,Polars 的惰性执行也能优化查询效率

不适合用 Polars:需要丰富第三方库生态时(如 statsmodels、sklearn 接受 Pandas 输入)

Q2: Polars 的 LazyFrame 有什么优势?

答案

  • 查询优化:自动执行谓词下推、投影下推等优化
  • 减少内存:scan 模式不需要一次性加载全部数据
  • 自动并行:利用所有 CPU 核心
  • 类似 Spark 的执行计划优化,但在单机上运行

Q3: Parquet 格式为什么比 CSV 快?

答案

  • 列式存储:只读需要的列,不用扫描整行
  • 内置压缩:文件体积小 5~10 倍
  • 类型信息:不需要推断类型,直接加载
  • 二进制格式:无需解析文本
  • 推荐在数据管道中使用 Parquet 替代 CSV

相关链接