在 Rust 中逐行高效地构建 Polars DataFrame
Efficiently build a Polars DataFrame row by row in Rust
我想使用 Rust 创建一个大型 Polars DataFrame
,使用从网页上抓取的数据逐行构建它。执行此操作的有效方法是什么?
看起来 DataFrame
应该从 Series
的 Vec
创建,而不是向空 DataFrame 添加行。但是,一个Series
应该如何高效的搭建起来呢?我可以创建一个 Vec
,然后从 Vec
创建一个 Series
,但这听起来像是最终会复制所有元素。有没有一种方法可以逐个元素地构建一个 Series
,然后从中构建一个 DataFrame
?
实际上,我将使用 Rayon 并行构建多个 DataFrame,然后将它们组合起来,但看起来 vstack 可以满足我的要求。我不知道如何有效地创建单个 DataFrames。
我确实查看了 CSV 解析器的源代码,但它非常复杂,而且可能经过高度优化,但是否有一种仍然相当有效的简单方法?
pub fn from_vec(
name: &str,
v: Vec<<T as PolarsNumericType>::Native, Global>
) -> ChunkedArray<T>
Create a new ChunkedArray by taking ownership of the Vec. This operation is zero copy.
here就是link。然后你可以在上面调用 into_series
。
最简单的答案,如果不是最高效的话,就是只维护一张向量图,然后将它们转换成序列,然后一次性全部输入 DataFrame。
let columns = BTreeMap::new();
for datum in get_data_from_web() {
// For simplicity suppose datum is itself a BTreeMap
// (More likely it's a serde_json::Value)
// It's assumed that every datum has the same keys; if not, the
// Vecs won't have the same length
// It's also assumed that the values of datum are all of the same known type
for (k, v) in datum {
columns.entry(k).or_insert(vec![]).push(v);
}
}
let df = DataFrame::new(
columns.into_iter()
.map(|(name, values)| Series::new(name, values))
.collect::<Vec<_>>()
).unwrap();
我想使用 Rust 创建一个大型 Polars DataFrame
,使用从网页上抓取的数据逐行构建它。执行此操作的有效方法是什么?
看起来 DataFrame
应该从 Series
的 Vec
创建,而不是向空 DataFrame 添加行。但是,一个Series
应该如何高效的搭建起来呢?我可以创建一个 Vec
,然后从 Vec
创建一个 Series
,但这听起来像是最终会复制所有元素。有没有一种方法可以逐个元素地构建一个 Series
,然后从中构建一个 DataFrame
?
实际上,我将使用 Rayon 并行构建多个 DataFrame,然后将它们组合起来,但看起来 vstack 可以满足我的要求。我不知道如何有效地创建单个 DataFrames。
我确实查看了 CSV 解析器的源代码,但它非常复杂,而且可能经过高度优化,但是否有一种仍然相当有效的简单方法?
pub fn from_vec(
name: &str,
v: Vec<<T as PolarsNumericType>::Native, Global>
) -> ChunkedArray<T>
Create a new ChunkedArray by taking ownership of the Vec. This operation is zero copy.
here就是link。然后你可以在上面调用 into_series
。
最简单的答案,如果不是最高效的话,就是只维护一张向量图,然后将它们转换成序列,然后一次性全部输入 DataFrame。
let columns = BTreeMap::new();
for datum in get_data_from_web() {
// For simplicity suppose datum is itself a BTreeMap
// (More likely it's a serde_json::Value)
// It's assumed that every datum has the same keys; if not, the
// Vecs won't have the same length
// It's also assumed that the values of datum are all of the same known type
for (k, v) in datum {
columns.entry(k).or_insert(vec![]).push(v);
}
}
let df = DataFrame::new(
columns.into_iter()
.map(|(name, values)| Series::new(name, values))
.collect::<Vec<_>>()
).unwrap();