Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-ops/src/series/ops/moment.rs
6939 views
1
use polars_compute::moment::{KurtosisState, SkewState, kurtosis, skew};
2
use polars_core::prelude::*;
3
4
use crate::prelude::SeriesSealed;
5
6
pub trait MomentSeries: SeriesSealed {
7
/// Compute the sample skewness of a data set.
8
///
9
/// For normally distributed data, the skewness should be about zero. For
10
/// uni-modal continuous distributions, a skewness value greater than zero means
11
/// that there is more weight in the right tail of the distribution. The
12
/// function `skewtest` can be used to determine if the skewness value
13
/// is close enough to zero, statistically speaking.
14
///
15
/// see: [scipy](https://github.com/scipy/scipy/blob/47bb6febaa10658c72962b9615d5d5aa2513fa3a/scipy/stats/stats.py#L1024)
16
fn skew(&self, bias: bool) -> PolarsResult<Option<f64>> {
17
let s = self.as_series();
18
let s = s.cast(&DataType::Float64)?;
19
let ca = s.f64().unwrap();
20
21
let mut state = SkewState::default();
22
for arr in ca.downcast_iter() {
23
state.combine(&skew(arr));
24
}
25
Ok(state.finalize(bias))
26
}
27
28
/// Compute the kurtosis (Fisher or Pearson) of a dataset.
29
///
30
/// Kurtosis is the fourth central moment divided by the square of the
31
/// variance. If Fisher's definition is used, then 3.0 is subtracted from
32
/// the result to give 0.0 for a normal distribution.
33
/// If bias is `false` then the kurtosis is calculated using k statistics to
34
/// eliminate bias coming from biased moment estimators
35
///
36
/// see: [scipy](https://github.com/scipy/scipy/blob/47bb6febaa10658c72962b9615d5d5aa2513fa3a/scipy/stats/stats.py#L1027)
37
fn kurtosis(&self, fisher: bool, bias: bool) -> PolarsResult<Option<f64>> {
38
let s = self.as_series();
39
let s = s.cast(&DataType::Float64)?;
40
let ca = s.f64().unwrap();
41
42
let mut state = KurtosisState::default();
43
for arr in ca.downcast_iter() {
44
state.combine(&kurtosis(arr));
45
}
46
Ok(state.finalize(fisher, bias))
47
}
48
}
49
50
impl MomentSeries for Series {}
51
52
#[cfg(test)]
53
mod test {
54
use super::*;
55
56
#[test]
57
fn test_skew() -> PolarsResult<()> {
58
let s = Series::new(PlSmallStr::EMPTY, &[1, 2, 3, 4, 5, 23]);
59
let s2 = Series::new(
60
PlSmallStr::EMPTY,
61
&[Some(1), Some(2), Some(3), None, Some(1)],
62
);
63
64
assert!((s.skew(false)?.unwrap() - 2.2905330058490514).abs() < 0.0001);
65
assert!((s.skew(true)?.unwrap() - 1.6727687946848508).abs() < 0.0001);
66
67
assert!((s2.skew(false)?.unwrap() - 0.8545630383279711).abs() < 0.0001);
68
assert!((s2.skew(true)?.unwrap() - 0.49338220021815865).abs() < 0.0001);
69
70
Ok(())
71
}
72
73
#[test]
74
fn test_kurtosis() -> PolarsResult<()> {
75
let s = Series::new(PlSmallStr::EMPTY, &[1, 2, 3, 4, 5, 23]);
76
77
assert!((s.kurtosis(true, true)?.unwrap() - 0.9945668771797536).abs() < 0.0001);
78
assert!((s.kurtosis(true, false)?.unwrap() - 5.400820058440946).abs() < 0.0001);
79
assert!((s.kurtosis(false, true)?.unwrap() - 3.994566877179754).abs() < 0.0001);
80
assert!((s.kurtosis(false, false)?.unwrap() - 8.400820058440946).abs() < 0.0001);
81
82
let s2 = Series::new(
83
PlSmallStr::EMPTY,
84
&[Some(1), Some(2), Some(3), None, Some(1), Some(2), Some(3)],
85
);
86
assert!((s2.kurtosis(true, true)?.unwrap() - (-1.5)).abs() < 0.0001);
87
assert!((s2.kurtosis(true, false)?.unwrap() - (-1.875)).abs() < 0.0001);
88
assert!((s2.kurtosis(false, true)?.unwrap() - 1.5).abs() < 0.0001);
89
assert!((s2.kurtosis(false, false)?.unwrap() - 1.125).abs() < 0.0001);
90
91
Ok(())
92
}
93
}
94
95