如何在Polars透视表中按数据类型批量执行fill_null操作
Absolutely! Polars has you covered here—you can absolutely perform type-based bulk fill_null operations, which mirrors the behavior of dplyr's old mutate_if function. No need to manually list out every column name anymore.
Your Original Approach (Manual Column Specification)
First, let's recap your initial implementation where you had to target columns by name:
import polars as pl scores = pl.DataFrame( { "zone": ["North", "North", "North", "South", "South", "East", "East", "East", "East"], "funding": ["yes", "yes", "no", "no", "no", "no", "no", "yes", "yes"], "score": [78, 39, 76, 56, 67, 89, 100, 55, 80], } ) ( scores.group_by("zone", "funding").len() .with_columns( pl.col("len").over("funding"), pl.format( "{}%", (pl.col("len") * 100 / pl.sum("len")) .over("funding") .round(2), ).alias("perc"), ) .pivot("funding", index="zone") .with_columns( pl.col("len_yes").fill_null(0), pl.col("perc_yes").fill_null("0%") ) )
Optimized Solution (Type-Based Bulk Fill)
Here's the streamlined version that uses Polars' type selection to batch-apply fill_null based on column data types:
( scores.group_by("zone", "funding").len() .with_columns( pl.col("len").over("funding"), pl.format( "{}%", (pl.col("len") * 100 / pl.sum("len")) .over("funding") .round(2), ).alias("perc"), ) .pivot("funding", index="zone") .with_columns( pl.exclude(pl.String).fill_null(0), # Fill all non-string columns with 0 pl.col(pl.String).fill_null("0%") # Fill all string columns with "0%" ) )
How This Works
pl.exclude(pl.String)selects every column that isn't a string type (in your case, the numericlen_*columns), then appliesfill_null(0)to all of them at once.pl.col(pl.String)targets only string-type columns (yourperc_*columns), applyingfill_null("0%")to each.
This approach is way more scalable—if you end up with more columns down the line, you won't have to update your code to add new column names; Polars will automatically handle all columns matching the specified types.
Result (Same as Your Original Output)
Running the optimized code gives you the exact same desired result:
shape: (3, 5) ┌───────┬────────┬─────────┬─────────┬──────────┐ │ zone ┆ len_no ┆ len_yes ┆ perc_no ┆ perc_yes │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ u32 ┆ u32 ┆ str ┆ str │ ╞═══════╪════════╪═════════╪═════════╪══════════╡ │ South ┆ 2 ┆ 0 ┆ 40.0% ┆ 0% │ │ North ┆ 1 ┆ 2 ┆ 20.0% ┆ 50.0% │ │ East ┆ 2 ┆ 2 ┆ 40.0% ┆ 50.0% │ └───────┴────────┴─────────┴─────────┴──────────┘
内容的提问来源于stack exchange,提问作者Vincent

