rs_stats/prob/
std_err.rs

1//! # Standard Error Calculation
2//!
3//! This module implements the standard error calculation, which measures
4//! the precision of the sample mean as an estimate of the population mean.
5//!
6//! ## Mathematical Definition
7//! The standard error is defined as:
8//!
9//! SE = σ / √n
10//!
11//! where:
12//! - σ is the sample standard deviation
13//! - n is the sample size
14//!
15//! ## Key Properties
16//! - Decreases as sample size increases
17//! - Measures the variability of the sample mean
18//! - Used in confidence intervals and hypothesis testing
19
20use crate::error::StatsResult;
21use crate::prob::std_dev;
22use num_traits::ToPrimitive;
23
24/// Calculate the standard error of a dataset
25///
26/// The standard error quantifies the uncertainty in the sample mean
27/// as an estimate of the population mean.
28///
29/// # Arguments
30/// * `data` - A slice of numeric values implementing `ToPrimitive`
31///
32/// # Returns
33/// * `StatsResult<f64>` - The standard error, or an error if the input is invalid
34///
35/// # Errors
36/// Returns `StatsError::EmptyData` if the input slice is empty.
37/// Returns `StatsError::ConversionError` if any value cannot be converted to f64.
38///
39/// # Examples
40/// ```
41/// use rs_stats::prob::std_err;
42///
43/// // Calculate standard error for a dataset
44/// let data = [1.0, 2.0, 3.0, 4.0, 5.0];
45/// let se = std_err(&data)?;
46/// assert!((se - 0.632455532).abs() < 1e-9);
47///
48/// // Handle empty input
49/// let empty_data: &[f64] = &[];
50/// assert!(std_err(empty_data).is_err());
51/// # Ok::<(), rs_stats::StatsError>(())
52/// ```
53#[inline]
54pub fn std_err<T>(data: &[T]) -> StatsResult<f64>
55where
56    T: ToPrimitive + std::fmt::Debug,
57{
58    std_dev(data).map(|std| std / (data.len() as f64).sqrt())
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    const EPSILON: f64 = 1e-9;
66
67    #[test]
68    fn test_std_err_integers() {
69        // Dataset: [1, 2, 3, 4, 5]
70        // Standard deviation of [1, 2, 3, 4, 5] is 1.414213562 (approx)
71        // Standard error should be std_dev / sqrt(n) = 1.414213562 / sqrt(5) = 0.632455532 (approx)
72        let data = vec![1, 2, 3, 4, 5];
73        let result = std_err(&data).unwrap();
74        let expected = 0.632455532; // Calculated value of the standard error
75        assert!(
76            (result - expected).abs() < EPSILON,
77            "Standard error should be approximately 0.632455532"
78        );
79    }
80
81    #[test]
82    fn test_std_err_floats() {
83        // Dataset: [1.0, 2.0, 3.0, 4.0, 5.0]
84        // Standard deviation of [1.0, 2.0, 3.0, 4.0, 5.0] is the same as for integers
85        let data = vec![1.0, 2.0, 3.0, 4.0, 5.0];
86        let result = std_err(&data).unwrap();
87        let expected = 0.632455532;
88        assert!(
89            (result - expected).abs() < EPSILON,
90            "Standard error for floats should be approximately 0.632455532"
91        );
92    }
93
94    #[test]
95    fn test_std_err_single_element() {
96        // Dataset with only one element: [5]
97        // Standard deviation is 0, and thus standard error should also be 0
98        let data = vec![5];
99        let result = std_err(&data).unwrap();
100        let expected = 0.0;
101        assert_eq!(
102            result, expected,
103            "Standard error for a single element should be 0.0"
104        );
105    }
106
107    #[test]
108    fn test_std_err_empty() {
109        // Empty dataset: []
110        // There should be no standard error, result should be an error
111        let data: Vec<i32> = vec![];
112        let result = std_err(&data);
113        assert!(result.is_err());
114        assert!(matches!(
115            result.unwrap_err(),
116            crate::error::StatsError::EmptyData { .. }
117        ));
118    }
119}