如何在Rust中使用ndarray从CSV创建时间序列数组?
使用ndarray从CSV创建时间序列数组的解决方案
问题背景
已有如下CSV数据:
date,value 1959-07-02,0.2930 1959-07-06,0.2910 1959-07-07,0.2820 1959-07-08,0.2846 1959-07-09,0.2760 1959-07-10,0.2757
已完成CSV反序列化(代码如下),需要生成两个ndarray::Array对象:一个存储日期(NaiveDate或字符串类型),一个存储f64数值,用于plotly-rs绘图。
反序列化代码:
use serde::Deserialize; use chrono::NaiveDate; use csv::{ReaderBuilder, Deserializer}; use serde::de; #[derive(Deserialize)] struct Record { #[serde(deserialize_with = "naive_date_time_from_str")] date: NaiveDate, value: f64 } fn naive_date_time_from_str<'de, D>(deserializer: D) -> Result<NaiveDate, D::Error> where D: Deserializer<'de>, { let s: String = Deserialize::deserialize(deserializer)?; NaiveDate::parse_from_str(&s, "%Y-%m-%d").map_err(de::Error::custom) }
实现步骤
ndarray的Array可直接从Vec转换而来,只需先将CSV中的日期和数值分别收集到两个Vec中,再转换为Array1即可。
修改后的main函数代码
use ndarray::Array1; use std::error::Error; fn main() -> Result<(), Box<dyn Error>> { let mut reader = ReaderBuilder::new() .has_headers(true) .delimiter(b',') .from_path("./data/timeseries.csv")?; // 初始化两个Vec用于收集数据 let mut dates: Vec<NaiveDate> = Vec::new(); let mut values: Vec<f64> = Vec::new(); // 遍历反序列化后的记录,收集数据到Vec for record in reader.deserialize::<Record>() { let record = record?; dates.push(record.date); values.push(record.value); } // 将Vec转换为ndarray的Array1 let date_array: Array1<NaiveDate> = Array1::from_vec(dates); let value_array: Array1<f64> = Array1::from_vec(values); // 验证结果(可选) println!("日期数组:{:?}", date_array); println!("数值数组:{:?}", value_array); Ok(()) }
关于日期类型的说明
如果plotly-rs对NaiveDate支持有限,可将日期转换为字符串类型存储,修改收集逻辑即可:
// 替换日期Vec的定义和收集代码 let mut date_strings: Vec<String> = Vec::new(); // ... date_strings.push(record.date.format("%Y-%m-%d").to_string()); // 转换为字符串类型的Array1 let date_string_array: Array1<String> = Array1::from_vec(date_strings);
内容的提问来源于stack exchange,提问作者accpnt
相关产品推荐
相关产品推荐

