Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to get non-contiguous slices from an ndarray?

Is it possible to index columns in a Rust ndarray matrix using a Vec rather than a Slice object? The only documentation I can find pertains to slicing using contiguous columns

Specifically, I am trying to implement something like the following code in Python:

x = np.array([[1,2,3,4,5,6], [7,8,9,10,11,12]])
idx = [0,1,2,4]
x[:, idx]

The outcome of x[:, idx] would be the subset of the matrix containing all rows and only columns described in idx, i.e., [0,1,2,4].

I am currently using ndarray (as the title suggests) but I cannot find a way to subset on non-contiguous slices. For instance, you can pass ndarray, which can take a Slice with a start, stop and an index, but I cannot find a way to pass a list of columns that cannot be described using a Slice object.

For instance:

#[macro_use]
extern crate ndarray;

fn main() {
    let mut x = array![[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]];
    let idx = vec![0, 1, 2, 4];
    // The following works as expected
    let y = x.slice(s![.., 0..2]);
    println!("{:?}", y);
    // This is conceptually what I would like to do but
    // It does not work.
    let y = x.slice(s![.., idx]);
}
like image 998
mandy Avatar asked Oct 16 '18 08:10

mandy


1 Answers

The analogue of "advanced indexing" in Numpy is the ArrayBase::select() method:

use ndarray::{array, Axis};

fn main() {
    let x = array![[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]];
    let idx = vec![0, 1, 2, 4];
    println!("{}", x.select(Axis(1), &idx));
}

producing the output

[[1, 2, 3, 5],
 [7, 8, 9, 11]]

Note that the resulting array is a copy of the selected elements (just as it is in Numpy). Depending on your use case, you may not need the copy; it's possible you can make do with just iterating over idx and using x.slice(s![.., i]) for all i in idx.

like image 93
Sven Marnach Avatar answered Oct 05 '22 20:10

Sven Marnach