我从m个正态分布中取样,每次n次,并将样本存储在二维正态分布中。然后,我需要将其转换为polars,因为我需要添加一些字符串列并进行大量的查询/聚合。
我认为将数组转换为dataframe的地方效率很低。极性文档似乎没有这样做的例子,我看到的每个例子都使用手工输入的少量数据,而我有来自10万个正态分布的10万个样本。
下面是示例的功能:
use rand_distr::{Normal, Distribution};
use polars::prelude::*;
use rayon::prelude::*;
use ndarray::Array2;
use cute::c;
#[macro_use]
extern crate fstrings;
fn multi_rnorm(n: usize, means: Vec<f64>, sds: Vec<f64>) -> Array2<f64> {
let mut preds: Array2<f64> = Array2::zeros((means.len(), n));
preds.axis_iter_mut(ndarray::Axis(0)).into_par_iter().enumerate().for_each(|(i, mut row)| {
let mut rng = rand::thread_rng();
(0..n).into_iter().for_each(|j| {
let normal = Normal::new(means[i], sds[i]).unwrap();
row[j as usize] = normal.sample(&mut rng);
})
});
preds
}下面是我如何创建数据框架:
let mut df: DataFrame = DataFrame::new(
c![Series::new(
&f!("{tuple.0}"),
tuple.1.to_vec()), for tuple in preds.axis_iter(ndarray::Axis(1))
.into_iter()
.enumerate()
.collect::<Vec<_>>()])
.unwrap();Main看起来如下:
fn main() {
let means = vec![0.0; 99_128];
let sds = vec![1.0; 99_128];
let preds = rprednorm(10000, means, sds);
let mut df: DataFrame = DataFrame::new(
c![Series::new(
&f!("{tuple.0}"),
tuple.1.to_vec()), for tuple in preds.axis_iter(ndarray::Axis(1))
.into_iter()
.enumerate()
.collect::<Vec<_>>()])
.unwrap();
}我正在使用可爱机箱中的c!宏来模拟python字典的理解,以及使用来自fstrings的f!()宏来执行字符串内插。
我试过用into_par_iter()代替into_iter(),但是没有加速。
我很惊讶没有看到任何关于如何在极性中这样做的例子,我想会有一些FromNdarray的实现,这样您就可以调用DataFrame::new(the_ndarray)或其他什么了。
我的实现看起来是否很好,还是更快呢?
发布于 2023-02-15 20:09:55
通过对DataFrame进行并行化,可以将Array2的创建优化为5倍。
let mut df: DataFrame = DataFrame::new(
preds.axis_iter(ndarray::Axis(1))
.into_par_iter()
.enumerate()
.map(|(i, col)| {
Series::new(
&f!("{i}"),
col.to_vec()
)
})
.collect::<Vec<Series>>()
).unwrap();https://codereview.stackexchange.com/questions/283305
复制相似问题