8 个版本 (4 个重大更改)
0.5.0 | 2023 年 8 月 22 日 |
---|---|
0.4.0 | 2021 年 7 月 19 日 |
0.3.0 | 2019 年 4 月 29 日 |
0.2.0 | 2019 年 3 月 21 日 |
0.1.1 | 2019 年 1 月 7 日 |
#222 in 数据结构
130KB
2K SLoC
Rust 数据读取器
到目前为止,此代码提供了与 Numpy 的 loadtxt 相似的功能。您可以在 doc.rs 的文档中了解更多信息。它目前旨在读取已知如何生成的数据。默认分隔符是任何空白字符。目前存在以下限制:
- 不计算在新行和注释行中的行数。
- 如果代码无法将字符串转换为支持的类型,则将失败。
- 从分隔符之间的任何字符串的前后都去除了空白字符。
- 所有读取的数据在转换为该类型时都需要是同一类型。
它支持以下原始类型:
u8 u16 u32 u64 u128 usize
i8 i16 i32 i64 i128
f32 f64
char bool String
原始 uint 和 int 使用 lexical crate 提供从字符串到给定类型的更快转换。浮点数使用 fast-float crate 从字符串转换为给定类型。其他类型使用内置的标准库 from_str 转换。读取的数据全部存储到向量中。从 load_text_*
方法返回一个结构体,该结构体提供读取的行数、从数据中读取的列数以及包含数据的向量。此结构体被包装在一个返回给用户的 Result 中。对于从 SSD 读取的 1GB float64 类型文件,我能够获得 190MB/s 的读取速度。
如果您感兴趣的类型支持 FromStr
特性,您还可以使用此 crate。下面的示例显示了如何使用 load_txt!
宏来加载自定义数据类型。
路线图
研究获取更大性能提升的读取大文件的方法。
示例
以下是如何使用代码的示例
extern crate anyhow;
#[macro_use]
extern crate data_reader;
use data_reader::reader::*;
use anyhow::Error;
use std::str;
use std::str::FromStr;
use std::vec::*;
//This example shows us how we might skip a footer file
fn load_txt_i32_test_sk_f(){
//The file here is the one included in the main folder.
let file = String::from("int_testv2.txt");
//A default constructor could look like this:
//let params = ReaderParams::default();
//The below could also look like the following:
//let params = ReaderParams{
// comments: Some(b'%'),
// skip_footer: Some(5),
// ..Default::default()
//};
let params = ReaderParams{
comments: Some(b'%'),
delimiter: Delimiter::WhiteSpace,
skip_header: None,
skip_footer: Some(5_usize),
usecols: None,
max_rows: None,
..Default::default()
};
let results = load_txt_i32(&file, ¶ms);
// Pattern matching for our results could look something like this.
// match results{
// Ok(results) => println!("Number of lines {}\nNumber of fields {}\nResults {:?}",results.num_lines, results.num_fields, results.results),
// Err(err) => println!("Error {:?}", err),
// }
assert_eq!(results.unwrap().results, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
}
以下是使用自定义类型的更详细示例。
extern crate anyhow;
#[macro_use]
extern crate data_reader;
use data_reader::reader::*;
use anyhow::Error;
use std::str;
use std::str::FromStr;
use std::vec::*;
//Everything needed for our custom type
#[derive(Debug, PartialEq, Clone)]
struct MinInt{
x: i32,
}
//A simple example of implementing the FromStr trait for our custom type
impl FromStr for MinInt{
type Err = Error;
fn from_str(s: &str) -> Result<MinInt, anyhow::Error> {
let temp = -1 * i32::from_str(s)?;
Ok(MinInt{x: temp})
}
}
//The test file for this has 0 commented lines in it but using a custom type
//The returned error is needed if we doing anything that's not in a function
fn load_txt_custom_test() -> Result<(), anyhow::Error> {
let file = String::from("int_testv2.txt");
let params = ReaderParams {
comments: Some(b'%'),
delimiter: Delimiter::WhiteSpace,
skip_header: None,
skip_footer: None,
usecols: None,
max_rows: None,
};
let ref_file = &file;
let ref_params = ¶ms;
//I found the type annotation was needed for this to compile
let results: Result<Box<dyn ReaderResults<MinInt>>, Error> = load_text!(ref_file, ref_params, MinInt);
let temp = results.unwrap().results.clone();
let vals: Vec<i32> = temp.iter().map(|x| x.x).collect();
assert_eq!(
vals,
vec![
-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14,
-15, -16, -17, -18, -19, -20, -21, -22, -23, -24, -25, -26, -27,
-28, -29, -30
]
);
Ok(())
}
版本
-
0.5.0 - 从failure crate迁移到anyhow。更新了lexical crate到6.0版本,这使得我们可以摆脱对fast-float crate的依赖,因为在该crate中的性能提升已经基本迁移到lexical。更新memmap2 crate到0.5.0版本。对于最终用户存在一些更改。首先,如果之前使用了这些,他们需要将
failure::Error
替换为anyhow::Error
。接下来,返回的结果现在是Box::<dyn ReaderResults<T>>
。现在parse_text
函数需要用户提供实现了trait RawReaderParse
的类型,例如parse_txt::<RawReaderResultsRows>
,这是旧的默认方法。这些更改是为了让用户现在可以选择以行主序或列主序解析数据。作为这些更改的一部分,ReaderParams
中添加了一个新的字段row_format
。它默认为true
,这将导致数据的行主序排序。现在ReaderResults*
包含了许多在它们上实现的有用函数,允许直接操作或获取对用户有意义的部分数据。 -
0.4.0 - 将UseCols更新为从0开始。更新了几个面向公共的函数以接受不同类型。在功能标志后添加了解析器的mmap版本。更新了多个crate,并将浮点解析后端从lexical更改为fast-float crate,以实现性能的大幅提升(在我的机器上从135MB/s提升到190MB/s)。向ReaderResults结构添加了一些函数,允许用户提取指定的行或列。
-
0.3.0 - 注意到ReaderParams结构体中use_cols字段的bug,允许输入不可用的值。此外,更新了ReaderParams注释字段,使其成为可选的。还添加了额外的文档,指出use_cols字段假定值从索引1开始。
-
0.2.0 - 添加了一个新的解析后端,它在大型的1GB f64文件中解析/读取速度提高了40%。将解析器暴露给最终用户,以便用户可以处理原始字节。现在任何支持
FromStr
trait的类型都可以进行转换。 -
0.1.3 - 更新了代码,以提供在lexical crate v2.0中的bug修复。
-
0.1.2 - 更新了代码中的注释和换行跟踪部分。现在代码可以正确跳过以空白字符开始的注释行和换行行,而且不会将包含多个注释字符的行计数多次。由于正确处理这些情况,从0.1.1和0.1.0版本中产生了性能回归。
-
0.1.1 - 需要更新docs.rs中的文档。
-
0.1.0 - 初始crates.io版本
依赖关系
~1MB
~16K SLoC