如何用Rust读取本地CSV文件为ndarray(支持未知形状)
读取未知形状CSV为ndarray的Rust实现
依赖准备
首先在Cargo.toml中添加所需依赖:
[dependencies] csv = "1.2" ndarray = "0.15"
实现代码
以下是完整的读取函数,支持自动推断CSV行列数,并处理常见错误:
use csv::ReaderBuilder; use ndarray::Array2; use std::error::Error; use std::fs::File; fn read_csv_to_ndarray(path: &str) -> Result<Array2<f64>, Box<dyn Error>> { let file = File::open(path)?; // 若CSV含表头,移除has_headers(false)并手动跳过第一行 let mut reader = ReaderBuilder::new().has_headers(false).from_reader(file); let mut rows = Vec::new(); let mut expected_cols: Option<usize> = None; for record in reader.records() { let record = record?; // 将CSV字符串记录转为f64数组 let row: Vec<f64> = record .iter() .map(|s| s.parse().map_err(|e| format!("解析'{}'失败: {}", s, e))) .collect::<Result<_, _>>()?; // 校验所有行的列数一致性 match expected_cols { Some(cols) if row.len() != cols => { return Err(format!("列数不匹配: 当前行{}列,预期{}列", row.len(), cols).into()) } None => expected_cols = Some(row.len()), _ => {} } rows.push(row); } // 处理空文件场景 let cols = expected_cols.ok_or("CSV文件无数据")?; let rows_count = rows.len(); // 将二维Vec转换为ndarray的Array2 let flat_data = rows.into_iter().flatten().collect(); Array2::from_shape_vec((rows_count, cols), flat_data).map_err(|e| e.into()) } // 使用示例 fn main() -> Result<(), Box<dyn Error>> { let data_array = read_csv_to_ndarray("sample.csv")?; println!("CSV数据形状: {:?}", data_array.shape()); println!("CSV内容:\n{}", data_array); Ok(()) }
关键说明
- 自动推断形状:遍历所有CSV行确定列数并校验一致性,统计行数后构建对应形状的
Array2 - 错误处理:覆盖文件打开失败、CSV解析错误、数值转换失败、列数不一致、空文件等场景
- 表头适配:若CSV含表头,移除
ReaderBuilder中的has_headers(false),并在遍历前调用reader.headers()?跳过表头行
内容的提问来源于stack exchange,提问作者Egorsky
相关产品推荐
相关产品推荐

