You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Polars过滤比Pandas等效实现慢?求优化方案

问题:Polars过滤函数在小数据集下比Pandas慢的优化方案?

我尝试用Polars实现一个过滤函数,但其速度明显慢于等效的Pandas实现。真实数据集规模为1000至10000行、100列,且需要处理多个不同数据集。以形状为(1000, 100)的数据集为例,Pandas版本速度快得多(Pandas耗时0.0006秒,Polars耗时0.0037秒),这超出预期。请问是否有更高效的Polars查询写法?或是小数据集下Pandas本就更具性能优势?

补充测试细节:

  • 当测试2列数据时Polars更快,但列数越多Polars速度越慢;
  • 当行数达到约500000行、100列时,Polars开始优于Pandas;
  • 实际场景中需要返回多个匹配最接近值的行;
  • 运行环境为Linux服务器。

原实现代码

Pandas版本

import pandas as pd
import time
import numpy as np

target_value = 0.5
data = np.random.rand(1000,100)
df = pd.DataFrame(data)

run_times = []
for i in range(100):
    st = time.perf_counter()
    df_filtered = df.loc[(df[0] - target_value).abs() == (df[0] - target_value).abs().min()]
    run_time = time.perf_counter() - st
    run_times.append(run_time)
print(f"avg pandas run: {sum(run_times)/len(run_times)}")

Polars版本

import polars as pl
import time
import numpy as np

target_value = 0.5
data = np.random.rand(1000,100)
df = pl.DataFrame(data)

run_times = []
for i in range(100):
    st = time.perf_counter()
    df = df.with_columns(abs_diff = (pl.col('column_0')-target_value).abs())
    df_filtered = df.filter(pl.col('abs_diff') == df['abs_diff'].min())
    run_time = time.perf_counter() - st
    run_times.append(run_time)
print(f"avg polars run: {sum(run_times)/len(run_times)}")

问题分析与优化方案

1. 原Polars代码慢的核心原因

原代码中每次循环都调用with_columns添加新列,这会复制整个DataFrame的所有100列数据,而Pandas的loc操作基于原数据的索引/视图操作,无额外列复制开销。当列数较多时,这种复制的性能损耗会被放大,导致Polars在小数据集下跑不过Pandas。

另外,Polars的查询优化、列存储等特性在小数据量时,优势不足以抵消其内部机制(如查询计划构建、列处理)带来的额外开销;而当数据量达到几十万行级别时,向量化和并行处理的优势会覆盖这些开销,反超Pandas。

2. 优化后的Polars写法

方案一:避免额外列的创建,直接在filter中完成计算

import polars as pl
import time
import numpy as np

target_value = 0.5
data = np.random.rand(1000,100)
df = pl.DataFrame(data)

run_times = []
for i in range(100):
    st = time.perf_counter()
    df_filtered = df.filter(
        (pl.col('column_0') - target_value).abs() == (pl.col('column_0') - target_value).abs().min()
    )
    run_time = time.perf_counter() - st
    run_times.append(run_time)
print(f"avg polars optimized run: {sum(run_times)/len(run_times)}")

直接在filter中计算绝对差值和最小值,无需创建临时列,避免了全量数据复制的开销。

方案二:使用懒执行(LazyFrame)优化查询计划

如果需要处理多个数据集或重复执行类似查询,懒执行可以让Polars提前优化整个查询流程,减少冗余计算:

import polars as pl
import time
import numpy as np

target_value = 0.5
data = np.random.rand(1000,100)
df = pl.DataFrame(data)

run_times = []
for i in range(100):
    st = time.perf_counter()
    df_filtered = df.lazy().filter(
        (pl.col('column_0') - target_value).abs() == (pl.col('column_0') - target_value).abs().min()
    ).collect()
    run_time = time.perf_counter() - st
    run_times.append(run_time)
print(f"avg polars lazy run: {sum(run_times)/len(run_times)}")

3. 效果验证

优化后的写法能显著降低小数据集下的Polars执行耗时,接近甚至在部分场景下追平Pandas的速度;同时保留了Polars在大数据量下的性能优势。


内容的提问来源于stack exchange,提问作者Raymond Han

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 11:20:57