using .quantile_mut() on Array1::<f64>
Hi guys, I'm trying to use .quantile_mut() on a 1D array of f64 numbers. I'm getting this error:
the trait bound `f64: std::cmp::Ord` is not satisfied
the trait `std::cmp::Ord` is not implemented for `f64
I have a few questions:
- Which type will work? It's not clear from the docs.
- Is there a reason for using the noisy float for the number between 0-1? If the function errors when it's not between 0-1, wouldnt a normal float work?
Rust's floats (f64 and f32) do not implement the Ord trait because of how f64::NAN and f32::NAN behave in comparisons - see this little snippet https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=6190375f8d1a48bc1a885ce38981ebea
If you remove Not a Number from the equation (using something like noisy-floats) than you recover the Ord trait and you can call .quantile_mut.
As an action item on our side, we should probably provide a PartialOrd version of quantile_mut, as we do for the other summary function.
Thanks for the quick response @LukeMathWalker , that's annoying f32/f64 doen't impelment Ord . I made my array n64's and it works great.
It was potentially me reading the docs wrong as I had the impression that the q value needed to be noisy rather than the array which didn't make much sense to me. Thanks for clearning it up!
The quantile_axis_skipnan_mut method on the QuantileExt trait may also be useful for your application since it can work directly on f32/f64 in the presence of NaN values. We should probably add an analogous method to Quantile1dExt; @LukeMathWalker is that what you were referring to in your comment?
@jturner314 that sounds like a great idea, thanks for pointing out quantile_axis_skipnan_mut, I could add an axis to my 1d arrays and use this but I think it's cleaner to stay in 1d.
Yes, that's what I meant @jturner314.
@CharlieBickerton Note that 1d arrays have a single axis (axis 0). quantile_axis_skipnan_mut returns an array with one less axis, so the result of calling it on a 1d array is a 0d array. To turn an 0d array into its element, you can use .into_scalar(). So, you could do this:
use ndarray::prelude::*;
use ndarray_stats::{interpolate::Nearest, QuantileExt};
use noisy_float::types::n64;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut arr: Array1<f64> = array![0., std::f64::NAN, 1., std::f64::NAN, 2., 3., 4.];
assert_eq!(
2.,
arr.quantile_axis_skipnan_mut(Axis(0), n64(0.5), &Nearest)?
.into_scalar()
);
Ok(())
}
It would be more convenient to have a .quantile_skipnan_mut() method in Quantile1dExt, as @LukeMathWalker pointed out.