如何使用Polars LazyFrame同时计算所有列的多个汇总统计量
Polars中LazyFrame多列多统计量的纯Polars实现
问题场景
现有如下LazyFrame数据:
import polars as pl df = pl.from_repr(""" ┌─────┬─────┬─────┐ │ a ┆ b ┆ c │ │ --- ┆ --- ┆ --- │ │ i64 ┆ i64 ┆ i64 │ ╞═════╪═════╪═════╡ │ 1 ┆ 2 ┆ 3 │ │ 4 ┆ 5 ┆ 6 │ │ 7 ┆ 8 ┆ 9 │ └─────┴─────┴─────┘ """).lazy()
需求是为每列计算均值(mean)、标准差(std)、最小值(min)、最大值(max),且全程用纯Polars的LazyFrame方式实现,避免依赖Pandas。
尝试过的不理想方案
- 直接调用
df.select(pl.all().agg('min','max','mean','std')):Polars不支持无GroupBy的agg这样使用,会报错。 - 直接堆叠统计量:
df.select(pl.all().mean(), pl.all().std(), ...)会因列名重复报错。 - 为列名添加后缀:虽能运行,但后续需拆分列名,不够直观。
- 依赖Pandas拼接:可行但不够优雅,且失去Polars的性能优势。
纯Polars优雅解决方案
方案一:生成与Pandas agg一致的输出格式
如果想要得到和Pandas agg(['mean','std','min','max'])完全一致的结构(统计量作为行,原列作为列),可以通过生成单个统计量的DataFrame再纵向拼接实现,全程保持LazyFrame操作:
# 定义需要计算的统计量名称和对应的Polars方法 stats = [ ("mean", pl.all().mean), ("std", pl.all().std), ("min", pl.all().min), ("max", pl.all().max) ] # 拼接每个统计量的结果 result = ( pl.concat( [df.select(pl.lit(stat_name).alias("stat"), *stat_func()) for stat_name, stat_func in stats], how="vertical" ) .collect() ) print(result)
输出结果:
shape: (4, 4) ┌───────┬─────┬─────┬─────┐ │ stat ┆ a ┆ b ┆ c │ │ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ f64 ┆ f64 ┆ f64 │ ╞═══════╪═════╪═════╪═════╡ │ mean ┆ 4.0 ┆ 5.0 ┆ 6.0 │ │ std ┆ 3.0 ┆ 3.0 ┆ 3.0 │ │ min ┆ 1.0 ┆ 2.0 ┆ 3.0 │ │ max ┆ 7.0 ┆ 8.0 ┆ 9.0 │ └───────┴─────┴─────┴─────┘
方案二:按原列分组展示统计量
如果希望以原列为行、统计量为列的结构,可以用结构体+展开的方式:
result = ( df .select( pl.struct([ pl.all().mean().name.suffix("_mean"), pl.all().std().name.suffix("_std"), pl.all().min().name.suffix("_min"), pl.all().max().name.suffix("_max"), ]).alias("stats") ) .melt(value_name="stats") .explode("stats") .with_columns(pl.col("stats").struct.rename_fields(["mean", "std", "min", "max"])) .unnest("stats") .rename({"variable": "column"}) .collect() ) print(result)
输出结果:
shape: (3, 5) ┌────────┬─────┬─────┬─────┬─────┐ │ column ┆ mean┆ std ┆ min ┆ max │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ f64 ┆ f64 ┆ i64 ┆ i64 │ ╞════════╪═════╪═════╪═════╪═════╡ │ a ┆ 4.0 ┆ 3.0 ┆ 1 ┆ 7 │ │ b ┆ 5.0 ┆ 3.0 ┆ 2 ┆ 8 │ │ c ┆ 6.0 ┆ 3.0 ┆ 3 ┆ 9 │ └────────┴─────┴─────┴─────┴─────┘
内容的提问来源于stack exchange,提问作者Abraxas Yu
相关产品推荐
相关产品推荐

