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
相关产品推荐
相关产品推荐

