Get statistics on entire multidimensional ndarray as if it were flat

New to ndarray, and Rust.

I've got some multidimensional arrays on my hands, for which it makes sense to get the variance or standard deviation of the entire array as if it were flat.

I can't figure out how to do that. The bottom code snippet is an example of why "var_axis" doesn't work -- basically, it'll take the variance axis-by-axis, but it won't do the whole array as one thing.

Attempts to flatten an array using ndarray just resulted on the borrow checker declaring war upon the innocent (me). What I would like is something on the order of:

let yay_I_have_an_answer = bob.some_flattening_magic().var_axis(Axis(0), 0.0);

#![allow(unused)]

use ndarray::{array, Axis};

fn main() {
    let bob = array!([1.0, -2.0], [3.0, 4.0]);
    let v = bob.var_axis(Axis(0), 0.0).var_axis(Axis(0), 0.0);
    
    println!("var_axis says: {}", v[[]]);

    let mut sum = 0.0;
    let mut sum_2 = 0.0;
    for b in bob.iter() {
        sum += b;
        sum_2 += b * b;
    }
    
    println!("element-by-element variance is: {}", (sum_2 - sum * sum / 4.0) / 4.0);
}

(Playground)

Output:

var_axis says: 16
element-by-element variance is: 5.25

Errors:

   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 2.10s
     Running `target/debug/playground`

I'm no expert with ndarray but a quick peek at the docs suggests that you can flatten the array using aview1(bob.as_slice().unwrap()). This seems to do the trick: playground.

Another approach that seems to do the same thing is:

bob.view().into_shape([4]).unwrap().var_axis(Axis(0), 0.0)

I used unwrap because the underlying slice is contiguous in your example, but apparently, reshaping doesn't (and isn't supposed to) work with non-contiguous arrays, e.g. views that skip elements.

1 Like

You can just iterate over the array with ndarray::ArrayBase - Rust or get the underlying buffer with ndarray::Array - Rust

Do you mean I can iterate over the array with the function that they provide, or that I can iterate over the array with my own algorithm?

Hah! Both of your suggestions work. I'll be using as_slice because the solution using into_shape requires me to calculate the array size, and my personal preference is to leave stuff like that lurking under the hood whenever possible.

I had been trying to use as_slice, but that's when the fight with the borrow checker started. I'm not entirely sure what I was doing wrong (I didn't save the code, alas) -- it could be the aview1 part that does the magic -- but your solution works with my code, and I'm happy.