Reputation: 207
I am trying to use the ndarray
crate to do some bioinformatics, but I can't seem to be able to create a matrix dynamically.
I have vectors of booleans that I would like to combine into a two-dimensional array. However, trying to flatten the vectors and using into_shape
does not retain a correct order of the elements.
Thus I tried to create an empty array and concatenate rows into it, however this gives me an error I cannot comprehend. I know the empty array does not have the same dimensions but I cannot find a way to cast an empty array to the correct type and dimensions.
use ndarray::{concatenate, Array, Axis, Ix2};
fn main() {
#[rustfmt::skip]
let vector_of_vectors = vec![
vec![true, false, true],
vec![false, true, false],
];
let mut matrix: Array<bool, Ix2> = ndarray::array![];
for array in vector_of_vectors.iter() {
matrix = concatenate![Axis(0), matrix, Array::from(array.clone())];
}
}
error[E0308]: mismatched types
--> src/main.rs:12:18
|
12 | matrix = concatenate![Axis(0), matrix, Array::from(array.clone())];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an array with a fixed size of 2 elements, found one with 1 element
|
= note: expected struct `ArrayBase<ViewRepr<&bool>, Dim<[usize; 2]>>`
found struct `ArrayBase<ViewRepr<&bool>, Dim<[usize; 1]>>`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
Upvotes: 5
Views: 7111
Reputation: 5545
See the documentation for ndarray
:
use ndarray::{Array2, Axis};
fn main() {
#[rustfmt::skip]
let rand_vec = vec![
vec![true, false, true],
vec![false, true, false],
];
let mut arr = Array2::<bool>::default((2, 3));
for (i, mut row) in arr.axis_iter_mut(Axis(0)).enumerate() {
for (j, col) in row.iter_mut().enumerate() {
*col = rand_vec[i][j];
}
}
}
The documentation suggests to efficiently flatten the Vec
using extend_from_slice
and pass the flattened result to Array2::from_shape_vec
:
use ndarray::Array2;
fn main() {
// A Vec<Vec<bool>> with a random length of rows and columns
let rand_vec = gen_rand_vec();
let mut data = Vec::new();
let ncols = rand_vec.first().map_or(0, |row| row.len());
let mut nrows = 0;
for i in 0..rand_vec.len() {
data.extend_from_slice(&rand_vec[i]);
nrows += 1;
}
let arr = Array2::from_shape_vec((nrows, ncols), data).unwrap();
}
Given the former input for rand_vec
, both examples will give you:
[
[true, false, true],
[false, true, false],
]
Upvotes: 6