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

Polars(Rust)中如何用众数填充Cabin列的空值?

问题:Polars(Rust)中用众数填充Cabin列空值无效

我在泰坦尼克数据集上使用Polars(Rust)处理数据,发现Cabin列存在大量空值,尝试用fill_null方法以该列的众数填充空值,但空值数量完全没变化,相关代码及输出如下,请帮忙找出问题所在?

fn main() -> Result<()> {
    let q = LazyCsvReader::new("data/train.csv")
        .has_header(true)
        .finish()?;

    let df = q
        .collect()?;

    let fill = df.clone()
        .lazy()
        .with_columns([col("Cabin").fill_null(col("Cabin").mode())])
        .collect()?;

    println!("{:?}", df.null_count());
    println!("{:?}", fill.null_count());

    Ok(())
}

输出:

shape: (1, 12)
┌─────────────┬──────────┬────────┬──────┬───┬────────┬──────┬───────┬──────────┐
│ PassengerId ┆ Survived ┆ Pclass ┆ Name ┆ … ┆ Ticket ┆ Fare ┆ Cabin ┆ Embarked │
│ ---         ┆ ---      ┆ ---    ┆ ---  ┆   ┆ ---    ┆ ---  ┆ ---   ┆ ---      │
│ u32         ┆ u32      ┆ u32    ┆ u32  ┆   ┆ u32    ┆ u32  ┆ u32   ┆ u32      │
╞═════════════╪══════════╪════════╪══════╪═══╪════════╪══════╪═══════╪══════════╡
│ 0           ┆ 0        ┆ 0      ┆ 0    ┆ … ┆ 0      ┆ 0    ┆ 687   ┆ 2        │
└─────────────┴──────────┴────────┴──────┴───┴────────┴──────┴───────┴──────────┘
shape: (1, 12)
┌─────────────┬──────────┬────────┬──────┬───┬────────┬──────┬───────┬──────────┐
│ PassengerId ┆ Survived ┆ Pclass ┆ Name ┆ … ┆ Ticket ┆ Fare ┆ Cabin ┆ Embarked │
│ ---         ┆ ---      ┆ ---    ┆ ---  ┆   ┆ ---    ┆ ---  ┆ ---   ┆ ---      │
│ u32         ┆ u32      ┆ u32    ┆ u32  ┆   ┆ u32    ┆ u32  ┆ u32   ┆ u32      │
╞═════════════╪══════════╪════════╪══════╪═══╪════════╪══════╪═══════╪══════════╡
│ 0           ┆ 0        ┆ 0      ┆ 0    ┆ … ┆ 0      ┆ 0    ┆ 687   ┆ 2        │
└─────────────┴──────────┴────────┴──────┴───┴────────┴──────┴───────┴──────────┘

解决方案

问题根源在于col("Cabin").mode()的返回值类型:

  • Polars的mode()函数返回的是包含众数的列表(支持多众数场景),而fill_null()需要接收单个标量值,直接传入列表会导致填充逻辑无法触发,空值自然不会被替换。
  • 你需要从mode的结果中提取出单个众数值(泰坦尼克数据集的Cabin列众数唯一),再传入fill_null。

修正方案1:提前计算众数标量值

fn main() -> Result<()> {
    let q = LazyCsvReader::new("data/train.csv")
        .has_header(true)
        .finish()?;

    let df = q.collect()?;

    // 计算Cabin列的众数并提取第一个值(数据集众数唯一)
    let cabin_mode = df
        .lazy()
        .select([col("Cabin").mode().alias("mode")])
        .collect()?
        .column("mode")?
        .str()
        .get(0)
        .unwrap() // 实际项目中建议处理None情况,避免panic
        .to_string();

    let fill = df
        .clone()
        .lazy()
        .with_columns([col("Cabin").fill_null(lit(cabin_mode))])
        .collect()?;

    println!("原数据空值计数:\n{:?}", df.null_count());
    println!("填充后空值计数:\n{:?}", fill.null_count());

    Ok(())
}

修正方案2:在Lazy Pipeline中直接提取众数

无需提前collect,直接在Lazy API中用first()提取众数的第一个值:

fn main() -> Result<()> {
    let q = LazyCsvReader::new("data/train.csv")
        .has_header(true)
        .finish()?;

    let df = q.collect()?;

    let fill = df
        .clone()
        .lazy()
        .with_columns([
            col("Cabin").fill_null(
                col("Cabin").mode().first() // 直接提取第一个众数
            )
        ])
        .collect()?;

    println!("原数据空值计数:\n{:?}", df.null_count());
    println!("填充后空值计数:\n{:?}", fill.null_count());

    Ok(())
}

修改后,Cabin列的空值会被正确填充为该列的众数,空值数量会变为0。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 21:34:53