12 个稳定版本

2.2.1 2022 年 3 月 30 日
2.2.0 2022 年 3 月 29 日
2.1.0 2021 年 3 月 27 日
1.4.0 2020 年 12 月 31 日
0.1.0 2020 年 6 月 30 日

#897 in 文本处理

41 每月下载量

MIT 许可证

155KB
4K SLoC

CSVSC

用于在 csv 文件上构建转换链的库。

文档

请访问 https://docs.rs/csvsc


lib.rs:

csvsc 是一个构建 csv 文件处理器的框架。

想象一下,你有 N 个具有相同结构的 csv 文件,你想要使用它们来创建 M 个新的 csv 文件,这些文件的信息以某种方式依赖于原始文件。csvcv 就是为了这个目的而构建的。使用这个工具,你可以构建一个处理链(行流),它将逐个读取输入文件,并生成带有修改的新输出文件。

快速入门

使用 cargo 开始一个新的二进制项目

$ cargo new --bin miprocesadordecsv

Cargo.toml 中将 csvscencoding 添加为依赖项。

[dependencies]
csvsc = "2.2"

现在开始构建你的处理链。指定输入(一个或多个 csv 文件)、转换和输出。

use csvsc::prelude::*;

let mut chain = InputStreamBuilder::from_paths(&[
// Put here the path to your source files, from 1 to a million
"test/assets/chicken_north.csv",
"test/assets/chicken_south.csv",
]).unwrap().build().unwrap()

// Here is where you do the magic: add columns, remove ones, filter
// the rows, group and aggregate, even probably transpose the data
// to fit your needs.

// Specify some (zero, one or many) output targets so that results of
// your computations get stored somewhere.
.flush(Target::path("data/output.csv")).unwrap()

.into_iter();

// And finally consume the stream, reporting any errors to stderr.
while let Some(item) = chain.next() {
if let Err(e) = item {
eprintln!("{}", e);
}
}

示例

获取你的输入文件,在这种情况下,我将使用这两个

chicken_north.csv

month,eggs per week
1,3
1,NaN
1,6
2,
2,4
2,8
3,5
3,1
3,8

chicken_south.csv

month,eggs per week
1,2
1,NaN
1,
2,7
2,8
2,23
3,3
3,2
3,12

现在构建你的处理链。

// main.rs
use csvsc::prelude::*;

use encoding::all::UTF_8;

let mut chain = InputStreamBuilder::from_paths(vec![
"test/assets/chicken_north.csv",
"test/assets/chicken_south.csv",
]).unwrap()

// optionally specify the encoding
.with_encoding(UTF_8)

// optionally add a column with the path of the source file as specified
// in the builder
.with_source_col("_source")

// build the row stream
.build().unwrap()

// Filter some columns with invalid values
.filter_col("eggs per week", |value| {
value.len() > 0 && value != "NaN"
}).unwrap()

// add a column with a value obtained from the filename ¡wow!
.add(
Column::with_name("region")
.from_column("_source")
.with_regex("_([a-z]+).csv").unwrap()
.definition("$1")
).unwrap()

// group by two columns, compute some aggregates
.group(["region", "month"], |row_stream| {
row_stream.reduce(vec![
Reducer::with_name("region").of_column("region").last("").unwrap(),
Reducer::with_name("month").of_column("month").last("").unwrap(),
Reducer::with_name("avg").of_column("eggs per week").average().unwrap(),
Reducer::with_name("sum").of_column("eggs per week").sum(0.0).unwrap(),
]).unwrap()
})

// Write a report to a single file that will contain all the data
.flush(
Target::path("data/report.csv")
).unwrap()

// This column will allow us to output to multiple files, in this case
// a report by month
.add(
Column::with_name("monthly report")
.from_all_previous()
.definition("data/monthly/{month}.csv")
).unwrap()

.del(vec!["month"])

// Write every row to a file specified by its `monthly report` column added
// previously
.flush(
Target::from_column("monthly report")
).unwrap()

// Pack the processing chain into an interator that can be consumed.
.into_iter();

// Consuming the iterator actually triggers all the transformations.
while let Some(item) = chain.next() {
item.unwrap();
}

这是输出结果

data/monthly/1.csv

region,avg,sum
south,2,2
north,4.5,9

data/monthly/2.csv

region,avg,sum
north,6,12
south,12.666666666666666,38

data/monthly/3.csv

region,avg,sum
north,4.666666666666667,14
south,5.666666666666667,17

data/report.csv

region,month,avg,sum
north,2,6,12
south,1,2,2
south,2,12.666666666666666,38
north,3,4.666666666666667,14
south,3,5.666666666666667,17
north,1,4.5,9

深入了解

查看 InputStreamBuilder 了解启动处理链和读取输入的更多选项。

前往 RowStream 文档以查看所有可用的转换以及将数据刷新到文件或标准 I/O 的选项。

依赖项

~7MB
~105K SLoC