pub fn new(
        x: &[f64],
        y: &[f64],
        w: &[f64],
        exception_values: &[f64],
    ) -> Result<Self, DiscrustError> {
        // Make exception values.
        let mut exception_values_ = ExceptionValues::new(exception_values);

        // Define all of the stats we will use
        let mut vals_ = Vec::new();
        let mut cuml_ones_ct_ = Vec::new();
        let mut cuml_zero_ct_ = Vec::new();
        let mut cuml_totals_ct_ = Vec::new();
        // First we will get the index needed to sort the vector x.
        let mut sort_tuples: Vec<(usize, &f64)> = x.iter().enumerate().collect();
        let no_exceptions = exception_values.is_empty();
        if no_exceptions {
            // Now sort these tuples by the float values of x.
            sort_tuples.sort_by(|a, b| a.1.partial_cmp(b.1).unwrap());
        } else {
            sort_tuples.sort_by(|a, b| nan_safe_compare(a.1, b.1));
            
        };
        let sort_index = sort_tuples.iter().map(|(i, _)| *i);

        let mut totals_idx = 0;
        let mut first_value = true;
        let mut x_ = f64::NAN;
        let mut y_;
        let mut w_;
        let mut total_ones_ = 0.0;
        let mut total_zero_ = 0.0;
        for i in sort_index {
            y_ = y[i];
            w_ = w[i];
            // Some error checking
            if y_.is_nan() {
                return Err(DiscrustError::ContainsNaN(String::from("y column")));
            }
            if w_.is_nan() {
                return Err(DiscrustError::ContainsNaN(String::from("weight column")));
            }
            if !no_exceptions {
                let e_idx = exception_values_.exception_idx(&x[i]);
                if x[i].is_nan() && e_idx == None {
                    return Err(DiscrustError::ContainsNaN(String::from(
                        "x column, but NaN is not an exception value",
                    )));
                }
                // If the value is equal to one of our exception_values_ update the exception_values_
                // and continue.
                if let Some(idx) = e_idx {
                    exception_values_.update_exception_values(idx, &w_, &y_);
                    if y_ == 1.0 {
                        total_ones_ += w_;
                    } else {
                        total_zero_ += w_;
                    }
                    continue;
                }
            }
            // If this is the first value, add to our vectors
            // Initializing them.
            if first_value {
                x_ = x[i];
                cuml_totals_ct_.push(w_);
                if y_ == 1.0 {
                    total_ones_ += w_;
                    cuml_ones_ct_.push(w_);
                    cuml_zero_ct_.push(0.0);
                } else {
                    total_zero_ += w_;
                    cuml_ones_ct_.push(0.0);
                    cuml_zero_ct_.push(w_);
                }
                vals_.push(x_);
            // If this is a new value, push, and cumulate
            // this won't panic, because we know these
            // vectors have values
            } else if x_ < x[i] {
                let t_last = cuml_totals_ct_[totals_idx];
                let o_last = cuml_ones_ct_[totals_idx];
                let z_last = cuml_zero_ct_[totals_idx];
                x_ = x[i];
                cuml_totals_ct_.push(w_ + t_last);
                if y_ == 1.0 {
                    total_ones_ += w_;
                    cuml_ones_ct_.push(w_ + o_last);
                    cuml_zero_ct_.push(z_last);
                } else {
                    total_zero_ += w_;
                    cuml_ones_ct_.push(o_last);
                    cuml_zero_ct_.push(w_ + z_last);
                }
                vals_.push(x_);
                totals_idx += 1;
            } else {
                cuml_totals_ct_[totals_idx] += w_;
                if y_ == 1.0 {
                    total_ones_ += w_;
                    cuml_ones_ct_[totals_idx] += w_;
                } else {
                    total_zero_ += w_;
                    cuml_zero_ct_[totals_idx] += w_;
                }
            }
            first_value = false;
        }
        exception_values_.calculate_iv_woe(total_ones_, total_zero_);

        Ok(Feature {
            vals_,
            cuml_ones_ct_,
            cuml_zero_ct_,
            cuml_totals_ct_,
            total_ones_,
            total_zero_,
            exception_values_,
        })
    }
/// Generate a new feature from a vector and it's
/// binary performance. All vectors provided should be
/// of the same length.
///
/// # Arguments
///
/// * `x` - A reference to a vector that will be used
///     discretized.
/// * `y` - A reference to a vector of 1s (positive class)
///     and 0s (negative class).
/// * `w` - A reference to a vector of weights. If the feature
///     should be unweighted, pass in a vector of 1s, `vec![1.0; y.len()]`.
Generate a new feature from a vector and it's
binary performance. All vectors provided should be
of the same length.
Generate a new feature from a vector and it ' s binary performance . All vectors provided should be of the same length .
pub fn new(
        x: &[f64],
        y: &[f64],
        w: &[f64],
        exception_values: &[f64],
    ) -> Result<Self, DiscrustError> {
        // Make exception values.
        let mut exception_values_ = ExceptionValues::new(exception_values);
        // Define all of the stats we will use
        let mut vals_ = Vec::new();
        let mut cuml_ones_ct_ = Vec::new();
        let mut cuml_zero_ct_ = Vec::new();
        let mut cuml_totals_ct_ = Vec::new();
        // First we will get the index needed to sort the vector x.
        let mut sort_tuples: Vec<(usize, &f64)> = x.iter().enumerate().collect();
        let no_exceptions = exception_values.is_empty();
        if no_exceptions {
            // Now sort these tuples by the float values of x.
            sort_tuples.sort_by(|a, b| a.1.partial_cmp(b.1).unwrap());
        } else {
            sort_tuples.sort_by(|a, b| nan_safe_compare(a.1, b.1));
        };
        let sort_index = sort_tuples.iter().map(|(i, _)| *i);
        let mut totals_idx = 0;
        let mut first_value = true;
        let mut x_ = f64::NAN;
        let mut y_;
        let mut w_;
        let mut total_ones_ = 0.0;
        let mut total_zero_ = 0.0;
        for i in sort_index {
            y_ = y[i];
            w_ = w[i];
            // Some error checking
            if y_.is_nan() {
                return Err(DiscrustError::ContainsNaN(String::from("y column")));
            }
            if w_.is_nan() {
                return Err(DiscrustError::ContainsNaN(String::from("weight column")));
            }
            if !no_exceptions {
                let e_idx = exception_values_.exception_idx(&x[i]);
                if x[i].is_nan() && e_idx == None {
                    return Err(DiscrustError::ContainsNaN(String::from(
                        "x column, but NaN is not an exception value",
                    )));
                }
                // If the value is equal to one of our exception_values_ update the exception_values_
                // and continue.
                if let Some(idx) = e_idx {
                    exception_values_.update_exception_values(idx, &w_, &y_);
                    if y_ == 1.0 {
                        total_ones_ += w_;
                    } else {
                        total_zero_ += w_;
                    }
                    continue;
                }
            }
            // If this is the first value, add to our vectors
            // Initializing them.
            if first_value {
                x_ = x[i];
                cuml_totals_ct_.push(w_);
                if y_ == 1.0 {
                    total_ones_ += w_;
                    cuml_ones_ct_.push(w_);
                    cuml_zero_ct_.push(0.0);
                } else {
                    total_zero_ += w_;
                    cuml_ones_ct_.push(0.0);
                    cuml_zero_ct_.push(w_);
                }
                vals_.push(x_);
            // If this is a new value, push, and cumulate
            // this won't panic, because we know these
            // vectors have values
            } else if x_ < x[i] {
                let t_last = cuml_totals_ct_[totals_idx];
                let o_last = cuml_ones_ct_[totals_idx];
                let z_last = cuml_zero_ct_[totals_idx];
                x_ = x[i];
                cuml_totals_ct_.push(w_ + t_last);
                if y_ == 1.0 {
                    total_ones_ += w_;
                    cuml_ones_ct_.push(w_ + o_last);
                    cuml_zero_ct_.push(z_last);
                } else {
                    total_zero_ += w_;
                    cuml_ones_ct_.push(o_last);
                    cuml_zero_ct_.push(w_ + z_last);
                }
                vals_.push(x_);
                totals_idx += 1;
            } else {
                cuml_totals_ct_[totals_idx] += w_;
                if y_ == 1.0 {
                    total_ones_ += w_;
                    cuml_ones_ct_[totals_idx] += w_;
                } else {
                    total_zero_ += w_;
                    cuml_zero_ct_[totals_idx] += w_;
                }
            }
            first_value = false;
        }
        exception_values_.calculate_iv_woe(total_ones_, total_zero_);
        Ok(Feature {
            vals_,
            cuml_ones_ct_,
            cuml_zero_ct_,
            cuml_totals_ct_,
            total_ones_,
            total_zero_,
            exception_values_,
        })
    }
pub fn new ( x : & [ f64 ] , y : & [ f64 ] , w : & [ f64 ] , exception_values : & [ f64 ] , ) -> Result < Self , DiscrustError > { // Make exception values. let mut exception_values_ = ExceptionValues :: new ( exception_values ) ; // Define all of the stats we will use let mut vals_ = Vec :: new ( ) ; let mut cuml_ones_ct_ = Vec :: new ( ) ; let mut cuml_zero_ct_ = Vec :: new ( ) ; let mut cuml_totals_ct_ = Vec :: new ( ) ; // First we will get the index needed to sort the vector x. let mut sort_tuples : Vec < ( usize , & f64 ) > = x . iter ( ) . enumerate ( ) . collect ( ) ; let no_exceptions = exception_values . is_empty ( ) ; if no_exceptions { // Now sort these tuples by the float values of x. sort_tuples . sort_by ( | a , b | a . 1 . partial_cmp ( b . 1 ) . unwrap ( ) ) ; } else { sort_tuples . sort_by ( | a , b | nan_safe_compare ( a . 1 , b . 1 ) ) ; } ; let sort_index = sort_tuples . iter ( ) . map ( | ( i , _ ) | * i ) ; let mut totals_idx = 0 ; let mut first_value = true ; let mut x_ = f64 :: NAN ; let mut y_ ; let mut w_ ; let mut total_ones_ = 0.0 ; let mut total_zero_ = 0.0 ; for i in sort_index { y_ = y [ i ] ; w_ = w [ i ] ; // Some error checking if y_ . is_nan ( ) { return Err ( DiscrustError :: ContainsNaN ( String :: from ( " " ) ) ) ; } if w_ . is_nan ( ) { return Err ( DiscrustError :: ContainsNaN ( String :: from ( " " ) ) ) ; } if ! no_exceptions { let e_idx = exception_values_ . exception_idx ( & x [ i ] ) ; if x [ i ] . is_nan ( ) && e_idx == None { return Err ( DiscrustError :: ContainsNaN ( String :: from ( " " , ) ) ) ; } // If the value is equal to one of our exception_values_ update the exception_values_ // and continue. if let Some ( idx ) = e_idx { exception_values_ . update_exception_values ( idx , & w_ , & y_ ) ; if y_ == 1.0 { total_ones_ += w_ ; } else { total_zero_ += w_ ; } continue ; } } // If this is the first value, add to our vectors // Initializing them. if first_value { x_ = x [ i ] ; cuml_totals_ct_ . push ( w_ ) ; if y_ == 1.0 { total_ones_ += w_ ; cuml_ones_ct_ . push ( w_ ) ; cuml_zero_ct_ . push ( 0.0 ) ; } else { total_zero_ += w_ ; cuml_ones_ct_ . push ( 0.0 ) ; cuml_zero_ct_ . push ( w_ ) ; } vals_ . push ( x_ ) ; // If this is a new value, push, and cumulate // this won't panic, because we know these // vectors have values } else if x_ < x [ i ] { let t_last = cuml_totals_ct_ [ totals_idx ] ; let o_last = cuml_ones_ct_ [ totals_idx ] ; let z_last = cuml_zero_ct_ [ totals_idx ] ; x_ = x [ i ] ; cuml_totals_ct_ . push ( w_ + t_last ) ; if y_ == 1.0 { total_ones_ += w_ ; cuml_ones_ct_ . push ( w_ + o_last ) ; cuml_zero_ct_ . push ( z_last ) ; } else { total_zero_ += w_ ; cuml_ones_ct_ . push ( o_last ) ; cuml_zero_ct_ . push ( w_ + z_last ) ; } vals_ . push ( x_ ) ; totals_idx += 1 ; } else { cuml_totals_ct_ [ totals_idx ] += w_ ; if y_ == 1.0 { total_ones_ += w_ ; cuml_ones_ct_ [ totals_idx ] += w_ ; } else { total_zero_ += w_ ; cuml_zero_ct_ [ totals_idx ] += w_ ; } } first_value = false ; } exception_values_ . calculate_iv_woe ( total_ones_ , total_zero_ ) ; Ok ( Feature { vals_ , cuml_ones_ct_ , cuml_zero_ct_ , cuml_totals_ct_ , total_ones_ , total_zero_ , exception_values_ , } ) }
Generate a new feature from a vector and it's
binary performance.
Generate a new feature from a vector and it ' s binary performance .
x
&[f64]
y
&[f64]
w
&[f64]
exception_values
&[f64]