Path: blob/main/crates/polars-ops/src/series/ops/moment.rs
6939 views
use polars_compute::moment::{KurtosisState, SkewState, kurtosis, skew};1use polars_core::prelude::*;23use crate::prelude::SeriesSealed;45pub trait MomentSeries: SeriesSealed {6/// Compute the sample skewness of a data set.7///8/// For normally distributed data, the skewness should be about zero. For9/// uni-modal continuous distributions, a skewness value greater than zero means10/// that there is more weight in the right tail of the distribution. The11/// function `skewtest` can be used to determine if the skewness value12/// is close enough to zero, statistically speaking.13///14/// see: [scipy](https://github.com/scipy/scipy/blob/47bb6febaa10658c72962b9615d5d5aa2513fa3a/scipy/stats/stats.py#L1024)15fn skew(&self, bias: bool) -> PolarsResult<Option<f64>> {16let s = self.as_series();17let s = s.cast(&DataType::Float64)?;18let ca = s.f64().unwrap();1920let mut state = SkewState::default();21for arr in ca.downcast_iter() {22state.combine(&skew(arr));23}24Ok(state.finalize(bias))25}2627/// Compute the kurtosis (Fisher or Pearson) of a dataset.28///29/// Kurtosis is the fourth central moment divided by the square of the30/// variance. If Fisher's definition is used, then 3.0 is subtracted from31/// the result to give 0.0 for a normal distribution.32/// If bias is `false` then the kurtosis is calculated using k statistics to33/// eliminate bias coming from biased moment estimators34///35/// see: [scipy](https://github.com/scipy/scipy/blob/47bb6febaa10658c72962b9615d5d5aa2513fa3a/scipy/stats/stats.py#L1027)36fn kurtosis(&self, fisher: bool, bias: bool) -> PolarsResult<Option<f64>> {37let s = self.as_series();38let s = s.cast(&DataType::Float64)?;39let ca = s.f64().unwrap();4041let mut state = KurtosisState::default();42for arr in ca.downcast_iter() {43state.combine(&kurtosis(arr));44}45Ok(state.finalize(fisher, bias))46}47}4849impl MomentSeries for Series {}5051#[cfg(test)]52mod test {53use super::*;5455#[test]56fn test_skew() -> PolarsResult<()> {57let s = Series::new(PlSmallStr::EMPTY, &[1, 2, 3, 4, 5, 23]);58let s2 = Series::new(59PlSmallStr::EMPTY,60&[Some(1), Some(2), Some(3), None, Some(1)],61);6263assert!((s.skew(false)?.unwrap() - 2.2905330058490514).abs() < 0.0001);64assert!((s.skew(true)?.unwrap() - 1.6727687946848508).abs() < 0.0001);6566assert!((s2.skew(false)?.unwrap() - 0.8545630383279711).abs() < 0.0001);67assert!((s2.skew(true)?.unwrap() - 0.49338220021815865).abs() < 0.0001);6869Ok(())70}7172#[test]73fn test_kurtosis() -> PolarsResult<()> {74let s = Series::new(PlSmallStr::EMPTY, &[1, 2, 3, 4, 5, 23]);7576assert!((s.kurtosis(true, true)?.unwrap() - 0.9945668771797536).abs() < 0.0001);77assert!((s.kurtosis(true, false)?.unwrap() - 5.400820058440946).abs() < 0.0001);78assert!((s.kurtosis(false, true)?.unwrap() - 3.994566877179754).abs() < 0.0001);79assert!((s.kurtosis(false, false)?.unwrap() - 8.400820058440946).abs() < 0.0001);8081let s2 = Series::new(82PlSmallStr::EMPTY,83&[Some(1), Some(2), Some(3), None, Some(1), Some(2), Some(3)],84);85assert!((s2.kurtosis(true, true)?.unwrap() - (-1.5)).abs() < 0.0001);86assert!((s2.kurtosis(true, false)?.unwrap() - (-1.875)).abs() < 0.0001);87assert!((s2.kurtosis(false, true)?.unwrap() - 1.5).abs() < 0.0001);88assert!((s2.kurtosis(false, false)?.unwrap() - 1.125).abs() < 0.0001);8990Ok(())91}92}939495