You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rust中将二维ndarray转换为Polars的List<f64> Series?

从ndarray::Array2高效转换为Polars List[f64]类型Series

原方法性能瓶颈分析

你当前实现的方法速度慢,核心原因是逐行创建小Series带来的额外开销:每个Series::from_vec都会初始化元数据、单独分配内存,频繁的小对象操作和内存拷贝会大幅降低效率。下面提供两种更高效的实现路径:


方法一:用ListChunkedBuilder直接构建(通用高效)

利用Polars的ListChunkedBuilder低阶API,直接写入行数据的切片,避免中间Series的创建,同时减少不必要的内存拷贝。

use ndarray::prelude::*;
use polars::prelude::*;
use polars::chunked_array::builder::ListChunkedBuilder;

fn array2_to_list_series(array: Array2<f64>) -> PolarsResult<Series> {
    let n_rows = array.nrows();
    let row_len = array.ncols();
    
    // 初始化ListChunked构建器,预分配总数据量的内存
    let mut builder = ListChunkedBuilder::new("", n_rows, row_len * n_rows);
    
    // 遍历每一行,直接写入原始数据切片
    for row in array.axis_iter(Axis(0)) {
        // 若ndarray行是连续内存布局,as_slice()可直接获取原始数据,无需to_vec()拷贝
        builder.append_slice(row.as_slice().unwrap())?;
    }
    
    Ok(builder.finish().into_series())
}

fn main() -> PolarsResult<()> {
    let array: Array2<f64> = array![[1., 2.], [3., 4.], [5., 6.]];
    let series = array2_to_list_series(array)?;
    
    println!("{}", series);
    Ok(())
}

方法二:基于连续内存的批量构建(最优性能)

如果你的ndarray是连续内存布局(比如C/F顺序的标准布局),可以一次性将整个数组展平,再通过偏移量构建ListArray,完全避免逐行处理的开销。

use ndarray::prelude::*;
use polars::prelude::*;
use polars::array::ListArray;

fn array2_to_list_series_contiguous(array: Array2<f64>) -> PolarsResult<Series> {
    // 确保数组为标准连续布局(非连续时自动转换)
    let contiguous_array = array.as_standard_layout();
    let raw_data = contiguous_array.as_slice().unwrap();
    let n_rows = contiguous_array.nrows();
    let row_len = contiguous_array.ncols();
    
    // 批量创建基础Float64ChunkedArray
    let values = Float64Chunked::new("", raw_data.to_vec());
    // 计算每个列表的起始偏移量和固定长度
    let offsets = (0..=n_rows).map(|i| (i * row_len) as i64).collect::<Vec<_>>();
    let lengths = vec![row_len as i64; n_rows];
    
    // 直接构建ListArray
    let list_array = ListArray::new(
        DataType::List(Box::new(DataType::Float64)),
        offsets.into(),
        values.into(),
        None,
    );
    
    Ok(list_array.into_series())
}

fn main() -> PolarsResult<()> {
    let array: Array2<f64> = array![[1., 2.], [3., 4.], [5., 6.]];
    let series = array2_to_list_series_contiguous(array)?;
    
    println!("{}", series);
    Ok(())
}

内容的提问来源于stack exchange,提问作者Azmy Rajab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 14:37:53