kernel_density_estimation/bandwidth/
silverman.rs

1//! Silverman's rule for bandwidth selection.
2
3use crate::bandwidth::Bandwidth;
4use crate::float::{float, KDEFloat};
5use crate::internal::{interquartile_range, variance};
6
7/// Silverman's rule for bandwidth selection.
8#[derive(Clone, Copy, Debug)]
9pub struct Silverman;
10
11impl<F: KDEFloat> Bandwidth<F> for Silverman {
12    fn bandwidth(&self, data: &[F]) -> F {
13        let var = variance(data);
14        let var_term = var.sqrt();
15        let iqr = interquartile_range(data);
16        let iqr_term = iqr / float!(1.349);
17        let n = float!(data.len());
18        let m = if var_term < iqr_term {
19            var_term
20        } else {
21            iqr_term
22        };
23        let numerator = float!(0.9) * m;
24        let denominator = n.powf(float!(0.2));
25        numerator / denominator
26    }
27}
28
29#[cfg(test)]
30mod tests {
31    use super::{Bandwidth, Silverman};
32    use approx::*;
33
34    #[test]
35    fn silverman() {
36        let data = vec![1.0, 1.5, 2.0, 2.5, 3.0];
37        let res = Silverman.bandwidth(&data);
38        assert_relative_eq!(res, 0.51568, epsilon = 1.0e-5);
39    }
40}