无需逐个指定列,为Polars部分列添加总计行(其余设为null)
无需逐个指定列生成Polars总计行的实现方法
首先给出原始DataFrame:
import polars as pl df = pl.DataFrame(dict( j=[2, 7, 1, 8], k=[False, True, True, False], l=['foo', 'bar', 'quux', 'bin'], u=[5.0, 8.0, 13.0, 21.0], ))
输出:
shape: (4, 4) ┌─────┬───────┬──────┬──────┐ │ j ┆ k ┆ l ┆ u │ │ --- ┆ --- ┆ --- ┆ --- │ │ i64 ┆ bool ┆ str ┆ f64 │ ╞═════╪═══════╪══════╪══════╡ │ 2 ┆ false ┆ foo ┆ 5.0 │ │ 7 ┆ true ┆ bar ┆ 8.0 │ │ 1 ┆ true ┆ quux ┆ 13.0 │ │ 8 ┆ false ┆ bin ┆ 21.0 │ └─────┴───────┴──────┴──────┘
我们需要生成仅部分列求和、其余列设为None的总计行,再通过pl.concat合并到原DataFrame,且保持列顺序。以下针对两种场景给出批量处理方案:
场景1:按特定数据类型列求和
比如对所有数值类型(i64、f64)的列求和,其他类型列设为None。可以利用Polars的列选择器批量处理,同时保留原列顺序:
# 定义需要求和的类型 numeric_dtypes = [pl.Int64, pl.Float64] # 生成总计行 df_sum_by_dtype = df.select( [ pl.col(col).sum() if pl.col(col).dtype in numeric_dtypes else pl.lit(None).alias(col) for col in df.columns ] ) # 合并原DataFrame与总计行 result_by_dtype = pl.concat([df, df_sum_by_dtype]) print(result_by_dtype)
输出:
shape: (5, 4) ┌─────┬───────┬──────┬──────┐ │ j ┆ k ┆ l ┆ u │ │ --- ┆ --- ┆ --- ┆ --- │ │ i64 ┆ bool ┆ str ┆ f64 │ ╞═════╪═══════╪══════╪══════╡ │ 2 ┆ false ┆ foo ┆ 5.0 │ │ 7 ┆ true ┆ bar ┆ 8.0 │ │ 1 ┆ true ┆ quux ┆ 13.0 │ │ 8 ┆ false ┆ bin ┆ 21.0 │ │ 18 ┆ null ┆ null ┆ 47.0 │ └─────┴───────┴──────┴──────┘
场景2:按特定列名求和
比如指定列名['j', 'u']进行求和,其余列设为None,同样批量处理:
# 定义需要求和的列名 sum_cols = ['j', 'u'] # 生成总计行 df_sum_by_names = df.select( [ pl.col(col).sum() if col in sum_cols else pl.lit(None).alias(col) for col in df.columns ] ) # 合并原DataFrame与总计行 result_by_names = pl.concat([df, df_sum_by_names]) print(result_by_names)
输出与场景1的最终结果一致。
更简洁的写法(利用Polars的when语法)
也可以用pl.when来简化列处理逻辑,以场景2为例:
df_sum_by_names = df.select( pl.col('*').when(pl.col('*').name.is_in(sum_cols)).then(pl.col('*').sum()).otherwise(None) )
这种写法无需遍历列名,同样能保持原列顺序,生成相同的总计行。
内容的提问来源于stack exchange,提问作者levant pied
相关产品推荐
相关产品推荐

