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

在Rust Polars中用自定义函数将&str转为f64的问题排查

问题解决:Polars中存储容量单位转换(Rust)

一、修复自定义函数的调用错误

你遇到的核心问题是**map方法的使用场景错误**,以及对Polars Expr API的理解偏差:

  1. with_columns是Polars的标准方法,确保导入polars::prelude::*即可使用,它支持传入多个Expr数组;with_column仅支持单个Expr。
  2. col("value").map()用于处理整个ChunkedArray,而你需要处理单个字符串元素,应使用map_elements方法。
  3. 避免在转换逻辑中用unwrap,改用Result返回错误,符合Polars的错误处理机制。

修复后的完整代码:

use polars::prelude::*;

pub fn convert_str_to_tb(value: &str) -> Result<f64, String> {
    let value = value.replace(",", "");
    let mut parts = value.split_whitespace();
    
    let num_str = parts.next().ok_or_else(|| "格式错误:缺失数字部分".to_string())?;
    let num = num_str.parse::<f64>().map_err(|e| format!("数字解析失败:{}", e))?;
    
    let unit = parts.next().ok_or_else(|| "格式错误:缺失单位部分".to_string())?;
    
    Ok(match unit {
        "KB" => num / 1_000_000_000.0,
        "MB" => num / 1_000_000.0,
        "GB" => num / 1_000.0,
        "TB" => num,
        _ => return Err(format!("不支持的单位:{}", unit)),
    })
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut df = df!(
        "volume" => &["volume01", "volume02", "volume03"],
        "value" => &["1,000 GB", "2,000,000 MB", "3 TB"]
    )?;

    df = df.with_columns([
        col("value")
            .map_elements(convert_str_to_tb, GetOutput::from_type(DataType::Float64))
            .alias("value_tb")
    ])?;

    println!("{}", df);
    Ok(())
}

二、无需自定义函数的原生DSL实现

Polars提供了丰富的字符串和条件表达式API,可完全用原生语法实现转换,还能利用向量化优化提升性能:

use polars::prelude::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut df = df!(
        "volume" => &["volume01", "volume02", "volume03"],
        "value" => &["1,000 GB", "2,000,000 MB", "3 TB"]
    )?;

    df = df.with_columns([
        // 移除逗号并按空格分割为数组
        col("value")
            .str()
            .replace(",", "", false)
            .str()
            .split(" ", false)
            .alias("split_value"),
        // 提取数字部分并转为f64
        col("split_value")
            .arr()
            .get(0)
            .str()
            .parse::<f64>()
            .alias("num"),
        // 提取单位部分
        col("split_value")
            .arr()
            .get(1)
            .alias("unit"),
        // 根据单位计算TB值
        when(col("unit") == "KB")
            .then(col("num") / 1_000_000_000.0)
            .when(col("unit") == "MB")
            .then(col("num") / 1_000_000.0)
            .when(col("unit") == "GB")
            .then(col("num") / 1_000.0)
            .when(col("unit") == "TB")
            .then(col("num"))
            .otherwise(lit(f64::NAN)) // 未知单位返回NaN,避免程序崩溃
            .alias("value_tb")
    ])?;

    // 可选:移除中间临时列
    df = df.drop(["split_value", "num", "unit"])?;

    println!("{}", df);
    Ok(())
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 12:37:36