Repository navigation
Clip #470
Description
Activity
Just wanted to comment saying yes, please, I would love that! It's a lot more concise and easier to read.
It's an easy win, if we want to implement one. What do you think @jturner314 @max-sixty @termoshtt?
I think so! The python ecosystem have
clip_lower(rather thanclip_min), which I think is clearer.No strong view on one vs two methods (or even both options). Rather than taking
Option, you could ask people to passinf/max_size, but less user-friendly.Would this mainly wrap mapv if implemented? I am interested in getting started contributing to ndarray and wondering if there might be any other magic involved in implementing this
Using what's currently available, we have this:
let arr = array![-2., -1., 0., 1., 2., f64::NAN]; // Clip lower, removing NANs. This can alternatively be written as // `v.max(-1.)`. For types implementing `Ord`, you could use `cmp::max` or // the `.max()` method. let clip_lower_remove = arr.mapv(|v| f64::max(v, -1.)); println!("{}", clip_lower_remove); // Clip lower, preserving NANs. This can alternatively be written like // `num::clamp(v, -1., f64::INFINITY)`. let clip_lower_preserve = arr.mapv(|v| if v < -1. { -1. } else { v }); println!("{}", clip_lower_preserve); // Clip upper, removing NANs. This can alternatively be written as // `v.min(1.)`. For types implementing `Ord`, you could use `cmp::min` or // the `.min()` method. let clip_upper_remove = arr.mapv(|v| f64::min(v, 1.)); println!("{}", clip_upper_remove); // Clip upper, preserving NANs. This can alternatively be written like // `num::clamp(v, f64::NEG_INFINITY, 1.)`. let clip_upper_preserve = arr.mapv(|v| if v > 1. { 1. } else { v }); println!("{}", clip_upper_preserve); // Clip, removing NANs. This case is weird, because it's unclear if the // lower or upper bound should be returned in the NAN case. let clip_remove = arr.mapv(|v| v.max(-1.).min(1.)); println!("{}", clip_remove); // Clip, preserving NANs. There are also nightly-only `.clamp()` methods // in `std` for `f32`, `f64`, and `Ord` types. let clip_preserve = arr.mapv(|v| num::clamp(v, -1., 1.)); println!("{}", clip_preserve);
In the most cases, I think it makes sense to preserve NANs. The double-sided clip using
mapvwithnum::clampis actually rather nice, but the one-sided clips aren't pretty (unless you want to remove NANs, which I think is the rare case).ndarrayprovides onlymap/mapv/mapv_inplace/etc. for other elementwise operations, so I think it makes the most sense rely on them for clipping as well (instead of adding newclip/clip_lower/etc. methods). Usingmap/mapvwithnum::clampis pretty nice. Maybe we could convince thenummaintainers to addclamp_lowerandclamp_upperfunctions to clean up the one-sided clips?If someone wanted to avoid using
mapand related methods, they could write an extension trait to add methods likeclip,clip_inplace,clip_move,exp,exp_inplace,exp_move, etc., toArrayBase.Reacted by Toshiki Teramura and blussFYI: This table shows how each language/library implements clamp.
rust-lang/rfcs#1961 (comment)Clip, preserving NANs. There are also nightly-only
.clamp()methodsThis seems to take a long time for stabilization. We should be consistent with it after its stabilization. rust-lang/rust#44095
Maybe we could convince the num maintainers to add clamp_lower and clamp_upper functions to clean up the one-sided clips?
This sounds better.
Just giving this a push, since clamp will become available in Rust 1.50
rust-lang/rust#77872I would vote for directly offering these methods as part of ndarray, since it's a common feature in other langues (python's ndarray, Torch,..).
I guess it makes sense to have clamp(..), clamp_min() and clamp_max().
Is there another function which we should add along the way?Reacted by Nil Goyette, lalberge and Dilshod Tadjibaev
I can't find a
numpy::clipfunction in ndarray. Is there one?If not, I know I can use something like
but do you think it would be better to have a clip function?
I can code it, I just wonder if we want it.