ndarray_glm/utility.rs
1//! utility functions for internal library use
2
3use ndarray::{concatenate, Array1, Array2, ArrayView2, Axis};
4use num_traits::{
5 identities::One,
6 {Float, FromPrimitive},
7};
8
9/// Prepend the input with a column of ones.
10/// Used to incorporate a constant intercept term in a regression.
11pub fn one_pad<T>(data: ArrayView2<T>) -> Array2<T>
12where
13 T: Copy + One,
14{
15 // create the ones column
16 let ones: Array2<T> = Array2::ones((data.nrows(), 1));
17 // This should be guaranteed to succeed since we are manually specifying the dimension
18 concatenate![Axis(1), ones, data]
19}
20
21/// Returns a standardization of a design matrix where rows are seperate
22/// observations and columns are different dependent variables. Each quantity
23/// has its mean subtracted and is then divided by the standard deviation.
24/// The normalization by the standard deviation is not performed if there is only 1
25/// observation, since such an operation is undefined.
26pub fn standardize<F: Float>(mut design: Array2<F>) -> Array2<F>
27where
28 F: Float + FromPrimitive + std::ops::DivAssign,
29{
30 let n_obs: usize = design.nrows();
31 if n_obs >= 1 {
32 // subtract the mean
33 design = &design - &design.mean_axis(Axis(0)).expect("mean should succeed here");
34 }
35 if n_obs >= 2 {
36 // divide by the population standard deviation
37 let std: Array1<F> = design.std_axis(Axis(0), F::zero());
38 // design = &design / &std;
39 design.zip_mut_with(&std, |x, &sig| {
40 if sig > F::zero() {
41 *x /= sig;
42 }
43 })
44 }
45 design
46}