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

如何无需中间collect操作,按条件筛选Polars LazyFrame列?

在Polars LazyFrame中仅执行一次collect完成列级条件筛选

我们经常需要移除Polars LazyFrame中不符合列级条件(如方差、缺失值数量、唯一值数量)的列。目前常见的实现方式是先评估列级条件并collect中间结果,再将结果传入原LazyFrame进行筛选,但这种方式需要两次collect操作。

例如筛选唯一值数量≥10的列,现有实现如下:

threshold = 10
df = ldf.select(
    ldf.select(pl.all().n_unique())
    .unpivot()
    .filter(pl.col("value") >= threshold)
    .select("variable")
    .collect() # 此处需执行中间求值
    .to_series()
    .to_list()
).collect()

希望能找到仅在末尾执行一次collect的实现方式。


实现方法(单次collect)

可以通过转置+窗口函数+二次转置的方式,全程在Lazy模式下完成列筛选,仅最后执行一次collect:

import polars as pl

threshold = 10
df = (
    ldf
    # 添加行索引,用于转置后恢复原数据结构
    .with_row_index("row_idx")
    # 将原数据转置:列→行
    .unpivot(index="row_idx", variable_name="col_name", value_name="col_value")
    # 用窗口函数计算每列的唯一值数量
    .with_columns(
        pl.col("col_value").n_unique().over("col_name").alias("col_n_unique")
    )
    # 筛选出唯一值数量达标的列
    .filter(pl.col("col_n_unique") >= threshold)
    # 转置回原数据格式:行→列
    .pivot(index="row_idx", columns="col_name", values="col_value")
    # 移除临时添加的行索引列
    .drop("row_idx")
    # 仅在此处执行一次collect
    .collect()
)

原理说明

  1. 转置数据:将原LazyFrame的列转为行,让列级统计可以通过窗口函数over("col_name")实现分组计算。
  2. 窗口函数统计:对每个列分组计算唯一值数量,全程保持Lazy状态,无需提前求值。
  3. 筛选符合条件的列:基于窗口函数的统计结果过滤行,保留达标列的数据。
  4. 转置恢复结构:将筛选后的行数据转回原列格式,最后仅执行一次collect完成全部计算。

扩展到其他列级条件

这种方式可以轻松适配其他列级筛选需求:

  • 筛选缺失值占比<10%的列:将窗口函数替换为pl.col("col_value").is_null().mean().over("col_name").alias("null_ratio"),过滤条件改为pl.col("null_ratio") < 0.1。
  • 筛选方差>5的列:窗口函数替换为pl.col("col_value").var().over("col_name").alias("col_var"),过滤条件改为pl.col("col_var") > 5。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 08:05:23