Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python3
- from collections import deque
- from decimal import Decimal
- from statistics import mean as st_mean, fmean as st_fmean, variance as st_var, stdev as st_stdev, pstdev as st_pstdev
- from typing import Sequence, Callable
- """
- This module provides custom statistical functions for calculating variance and standard deviation.
- Does a 1-pass mean function &/ a 1-pass standard deviation fxn exist? It's called Welford's method.
- Includes both population and sample versions using a 2-pass method.
- """
- # Type alias for a function that takes a sequence of floats and an optional float, and returns a float
- StatFunction = Callable[[Sequence[float], float | None], float]
- class StatisticalFunctions:
- """Class providing static methods for various statistical calculations."""
- @classmethod
- def float_pvariance(cls, data: Sequence[float], mean: float = None) -> float:
- """ Population variance (similar to statistics.pvariance). Uses floats.
- https://docs.python.org/3/library/statistics.html#statistics.pvariance
- """
- if mean is None:
- mean = st_fmean(data)
- return sum((x - mean) ** 2 for x in data) / len(data)
- @classmethod
- def decimal_pvariance(cls, data: Sequence[Decimal], mean: Decimal = None) -> Decimal:
- """ Population variance (similar to statistics.pvariance). Uses Decimals.
- https://docs.python.org/3/library/statistics.html#statistics.pvariance
- """
- if mean is None:
- mean = st_mean(data)
- return sum((x - mean) ** 2 for x in data) / len(data)
- @classmethod
- def float_pstdev(cls, data: Sequence[float], mean: float = None) -> float:
- """ Population standard deviation (similar to statistics.pstdev). Uses floats.
- https://docs.python.org/3/library/statistics.html#statistics.pstdev
- """
- variance = cls.float_pvariance(data, mean)
- return variance ** 0.5
- @classmethod
- def decimal_pstdev(cls, data: Sequence[Decimal], mean: Decimal = None) -> Decimal:
- """ Population standard deviation (similar to statistics.pstdev). Uses Decimals.
- https://docs.python.org/3/library/statistics.html#statistics.pstdev
- """
- variance = cls.decimal_pvariance(data, mean)
- return variance ** 0.5
- @classmethod
- def float_variance(cls, data: Sequence[float], mean: float = None) -> float:
- """ Sample variance (similar to statistics.variance). Uses floats.
- https://docs.python.org/3/library/statistics.html#statistics.variance
- """
- if mean is None:
- mean = st_fmean(data)
- return sum((x - mean) ** 2 for x in data) / (len(data) - 1)
- @classmethod
- def decimal_variance(cls, data: Sequence[Decimal], mean: Decimal = None) -> Decimal:
- """ Sample variance (similar to statistics.variance). Uses Decimals.
- https://docs.python.org/3/library/statistics.html#statistics.variance
- """
- if mean is None:
- mean = st_mean(data)
- return sum((x - mean) ** 2 for x in data) / (len(data) - 1)
- @classmethod
- def float_stdev(cls, data: Sequence[float], mean: float = None) -> float:
- """ Sample standard deviation (similar to statistics.stdev). Uses floats.
- https://docs.python.org/3/library/statistics.html#statistics.stdev
- """
- variance = cls.float_variance(data, mean)
- return variance ** 0.5
- @classmethod
- def decimal_stdev(cls, data: Sequence[Decimal], mean: Decimal = None) -> Decimal:
- """ Sample standard deviation (similar to statistics.stdev). Uses Decimals.
- https://docs.python.org/3/library/statistics.html#statistics.stdev
- """
- variance = cls.decimal_variance(data, mean)
- return variance ** 0.5
- @classmethod
- def complex_variance(cls, data: Sequence[complex], mean: complex = None) -> complex:
- """ Sample variance (similar to statistics.variance). Uses complex numbers.
- https://docs.python.org/3/library/statistics.html#statistics.variance
- """
- if mean is None:
- mean = sum(data) / len(data)
- return sum((x - mean) * (x - mean).conjugate() for x in data) / (len(data) - 1)
- @classmethod
- def complex_stdev(cls, data: Sequence[complex], mean: complex = None) -> complex:
- """ Sample standard deviation (similar to statistics.stdev). Uses complex numbers.
- https://docs.python.org/3/library/statistics.html#statistics.stdev
- """
- variance = cls.complex_variance(data, mean)
- return variance ** 0.5
- def one_pass_variance(data: Sequence[float], exact: bool) -> float:
- if len(data) < 2:
- return 0.0
- K: float = data[0]
- n: int = 0
- Ex = Ex2 = 0.0
- for x in data:
- n += 1
- Ex += x - K
- Ex2 += (x - K) ** 2
- variance = (Ex2 - Ex ** 2 / n) / (n - 1 if exact else n)
- return variance
- def two_pass_variance(data: Sequence[float], exact: bool) -> float:
- n: int = len(data)
- mean: float = sum(data) / n
- variance = sum((x - mean) ** 2 for x in data) / (n - 1 if exact else n)
- return variance
- def two_pass_variance2(data: Sequence[float], exact: bool) -> float:
- mean: float = st_mean(data)
- variance = sum((x - mean) ** 2 for x in data) / (len(data) - 1 if exact else len(data))
- return variance
- def two_pass_variance3(data: Sequence[float], exact: bool, mean: float = None) -> float:
- if mean is None:
- mean = st_mean(data)
- variance = sum((x - mean) ** 2 for x in data) / (len(data) - 1 if exact else len(data))
- return variance
- class StdDev:
- K: float
- Ex: float
- Ex2: float
- n: int
- def __init__(self):
- self.K = self.Ex = self.Ex2 = 0.0
- self.n = 0
- def add_variable(self, x: float) -> None:
- if self.n == 0:
- self.K = x
- self.n += 1
- self.Ex += x - self.K
- self.Ex2 += (x - self.K) ** 2
- def remove_variable(self, x: float) -> None:
- self.n -= 1
- self.Ex -= x - self.K
- self.Ex2 -= (x - self.K) ** 2
- @property
- def mean(self) -> float:
- return self.K + self.Ex / self.n
- @property
- def variance(self) -> float:
- return (self.Ex2 - self.Ex ** 2 / self.n) / (self.n - 1 if self.n > 1 else self.n)
Advertisement
Add Comment
Please, Sign In to add comment