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

我的Polars代码运行慢于同类Pandas代码,潜在原因有哪些?

Polars代码比同功能Pandas慢的潜在问题分析

针对你提供的Polars代码,以下是几个可能导致性能不如预期的关键点:

1. 聚合阶段重复执行过滤逻辑

在agg操作中,q25和q90重复调用了pl.col('costprice').filter(filter_price),q50_sell也单独执行了filter_sell_price过滤。即使Polars采用懒执行,重复的过滤条件会生成冗余计算步骤,数据量越大,重复计算的额外开销越明显。

2. 不必要的中间数据类型转换

代码中存在多处低效的内存操作:

  • 将category唯一值转换为Python列表category = groups['category'].unique().to_list(),但后续又通过groups.select(pl.col('category').unique())重新获取同一数据,完全可以直接用Polars表达式完成关联,避免来回转换的开销。
  • 最终步骤里groupby("category").all()会把每个分组的所有列打包成Python列表,再结合to_dict(as_series=False)转换为原生字典,这种操作会把Polars高效的列存储结构拆分为Python对象,数据量越大性能损耗越严重。

3. 全量笛卡尔积与外连接的冗余开销

通过cross join生成pl_index(所有日期-类别组合)后,再与groups做外连接并全局排序。如果类别或日期范围较大,笛卡尔积会生成大量空行,后续的外连接和排序会显著增加内存占用与计算时间。

4. 未启用Polars的懒执行优化

当前代码使用默认的立即执行模式(Eager Execution),Polars无法对整个查询链路做全局优化。对于多步骤数据处理,懒执行(Lazy Execution)可以合并过滤、聚合等操作,减少中间数据集的生成,大幅提升性能。


针对性优化建议

  1. 提前合并公共过滤条件:先过滤掉fake==0和flag==1的行,减少后续处理的数据量:
filtered_df = df_data.filter(past_dates & (pl.col('fake')==0) & (pl.col('flag')==1))

聚合时只需单独过滤价格字段:

.agg(
    q25=pl.col('costprice').filter(pl.col('costprice')>0).quantile(0.25),
    q90=pl.col('costprice').filter(pl.col('costprice')>0).quantile(0.9),
    q50_sell=pl.col('sellprice').filter(pl.col('sellprice')>0).quantile(0.5)
)
  1. 避免Python列表转换:直接用Polars表达式完成笛卡尔积:
pl_index = all_dates.join(groups.select('category').unique(), how='cross')
  1. 启用懒执行:将整个流程改为懒加载模式:
groups = (
    df_data.lazy()
    .filter(past_dates & (pl.col('fake')==0) & (pl.col('flag')==1))
    .groupby('category', 'dates')
    .agg(
        q25=pl.col('costprice').filter(pl.col('costprice')>0).quantile(0.25),
        q90=pl.col('costprice').filter(pl.col('costprice')>0).quantile(0.9),
        q50_sell=pl.col('sellprice').filter(pl.col('sellprice')>0).quantile(0.5)
    )
    .collect()
)
  1. 优化最终字典转换:如果业务允许,尽量保留Polars DataFrame格式;若必须转字典,可尝试按类别迭代提取,避免groupby.all()的开销:
groups = {}
for cat in df_final['category'].unique():
    cat_data = df_final.filter(pl.col('category')==cat).with_columns(pl.col('dates').dt.to_string('%Y-%m-%d'))
    groups[cat] = {
        **cat_data.to_dict(as_series=False),
        'Count': len(cat_data)
    }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 21:20:38