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

Rust中Polars将字符串日期列转换为datetime列的问题

问题

我用Polars读取CSV文件得到DataFrame,其中“Date”列是05 Jan 1997格式的字符串。想新增名为“datetime”的列,把该列转换成datetime格式。已知NaiveDate::parse_from_str(s, "%d %b %Y")可以转换单个字符串,但用apply批量处理时出现类型不匹配的编译错误:apply传递的是Series,而NaiveDate::parse_from_str需要&str,且返回值类型也不对。

尝试的代码:

let df_csv = match read_csv(&file_name) {
        Ok(some) => some,
        Err(err) => {
            eprintln!("Error: {}", err);
            process::exit(1);
        }
    };

// 提取Date和Close列
let df_csv = df_csv.select(["Date", "Close"]).unwrap();

// 尝试添加datetime列时出错
let out = df_csv.clone().lazy().select([
        col("Date"),
        col("Date").apply(|s| { 
            Ok(Some(NaiveDate::parse_from_str(&s, "%d %b %Y").unwrap()))} , GetOutput::default()
        )
        .alias("datetime"),
        col("Close")
    ]).collect();

编译错误:

Compiling stock_data_analysis v0.1.0 (/Users/hrishi/Projects/stock_data_analysis)
error[E0308]: mismatched types
   --> src/main.rs:89:47
    |
89  | ...     Ok(Some(NaiveDate::parse_from_str(&s, "%d %b %Y").unwr...
    |                 ------------------------- ^^ expected `&str`, found `&Series`
    |                 |
    |                 arguments to this function are incorrect
    |
    = note: expected reference `&str`
               found reference `&polars::prelude::Series`
error[E0308]: mismatched types
   --> src/main.rs:89:21
    |
89  | ...Ok(Some(NaiveDate::parse_from_str(&s, "%d %b %Y").unwrap()))}...
    |       ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Series`, found `NaiveDate`
解决方法

Polars的apply方法处理列时接收的是整个Series,而非单个元素,直接用NaiveDate::parse_from_str处理会导致类型不匹配。以下两种方式可以解决问题:

方法一:手动遍历Series元素(适合自定义解析逻辑)

将Series转为字符串迭代器,逐个解析后再构建Polars兼容的日期类型Series:

use polars::prelude::*;
use chrono::NaiveDate;

let out = df_csv.clone().lazy().select([
    col("Date"),
    col("Date")
        .apply(
            |s: Series| {
                // 转换为Utf8格式的Chunked数组,遍历每个字符串元素
                let parsed_dates: Vec<Option<NaiveDate>> = s
                    .utf8()
                    .unwrap()
                    .into_iter()
                    .map(|opt_str| {
                        // 解析每个字符串,失败则返回None(对应Polars的Null)
                        opt_str.and_then(|s| NaiveDate::parse_from_str(s, "%d %b %Y").ok())
                    })
                    .collect();
                // 将解析结果转为Polars的Date类型Series
                Ok(Series::new("datetime", parsed_dates))
            },
            GetOutput::from_type(DataType::Date),
        )
        .alias("datetime"),
    col("Close"),
])
.collect()?;

方法二:使用Polars内置strptime(推荐,性能更高)

Polars提供了矢量化的日期解析函数strptime,无需手动遍历,直接指定格式即可完成批量转换:

let out = df_csv.clone().lazy().select([
    col("Date"),
    col("Date")
        .str()
        .strptime(DataType::Date, "%d %b %Y")
        .alias("datetime"),
    col("Close"),
])
.collect()?;

关键说明

  • 方法一中,utf8().unwrap()将Series转为Utf8Chunked类型,into_iter()获取每个字符串的Option<&str>,解析失败时用ok()转为None,对应Polars中的Null值。
  • 方法二的strptime是Polars原生的矢量化操作,比手动遍历效率高很多,优先选择这种方式。
  • 两种方法都会自动处理解析失败的情况,将无效日期转为Null。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 02:35:16