Polars透视表求和时将空值视为0的问题及解决咨询
解决Polars透视表聚合时保留Null的问题
问题分析
你遇到两个核心问题:
- 默认
sum聚合会忽略Null值,导致分组内存在Null时仍返回非Null的求和结果(如AA-EU分组有一个Null,但返回1.5);全Null分组返回0.0(如BB-US),不符合"有Null则显示Null"的需求。 - 自定义lambda函数报错
AttributeError: 'function' object has no attribute '_pyexpr',因为Polars的pivot方法的aggregate_function参数要求传入Polars表达式(pl.Expr),而非普通Python函数。
解决方案
方法1:直接使用表达式作为聚合函数
通过pl.when().then().otherwise()构建聚合逻辑,判断分组内是否存在Null,再决定返回Null还是求和结果:
import polars as pl df = pl.DataFrame({ 'label': ['AA', 'CC', 'BB', 'AA', 'CC'], 'account': ['EU', 'US', 'US', 'EU', 'EU'], 'qty': [1.5, 43.2, None, None, 18.9] }) # 构建聚合表达式:分组内有Null则返回Null,否则返回sum agg_expr = pl.when(pl.col("qty").is_null().any()).then(None).otherwise(pl.col("qty").sum()) # 执行透视表 result = df.pivot( values='qty', index='label', columns='account', aggregate_function=agg_expr ) print(result)
方法2:先分组聚合再转透视表(兼容旧版Polars)
如果你的Polars版本不支持直接给pivot传表达式,可先通过group_by完成聚合逻辑,再转成透视表:
import polars as pl df = pl.DataFrame({ 'label': ['AA', 'CC', 'BB', 'AA', 'CC'], 'account': ['EU', 'US', 'US', 'EU', 'EU'], 'qty': [1.5, 43.2, None, None, 18.9] }) # 先分组聚合 agg_df = df.group_by(['label', 'account']).agg( pl.when(pl.col("qty").is_null().any()).then(None).otherwise(pl.col("qty").sum()).alias('qty') ) # 转成透视表 result = agg_df.pivot(values='qty', index='label', columns='account') print(result)
预期输出
两种方法都会得到符合需求的结果:
shape: (3, 3) ┌───────┬──────┬──────┐ │ label ┆ EU ┆ US │ │ --- ┆ --- ┆ --- │ │ str ┆ f64 ┆ f64 │ ╞═══════╪══════╪══════╡ │ AA ┆ null ┆ null │ │ CC ┆ 18.9 ┆ 43.2 │ │ BB ┆ null ┆ null │ └───────┴──────┴──────┘
内容的提问来源于stack exchange,提问作者Phil-ZXX
相关产品推荐
相关产品推荐

