import math
from dataclasses import dataclass
-from typing import Dict, Generic, Iterable, List, NamedTuple, Optional, Tuple, TypeVar
+from typing import Dict, Generic, Iterable, List, Optional, Tuple, TypeVar
T = TypeVar("T", int, float)
Bound = int
NEGATIVE_INFINITY = -math.inf
def __init__(self, buckets: List[Tuple[Bound, Bound]]):
- from math_utils import RunningMedian
+ from math_utils import NumericPopulation
self.buckets: Dict[Tuple[Bound, Bound], Count] = {}
for start_end in buckets:
raise Exception("Buckets overlap?!")
self.buckets[start_end] = 0
self.sigma: float = 0.0
- self.median: RunningMedian = RunningMedian()
+ self.stats: NumericPopulation = NumericPopulation()
self.maximum: Optional[T] = None
self.minimum: Optional[T] = None
self.count: Count = 0
self.count += 1
self.buckets[bucket] += 1
self.sigma += item
- self.median.add_number(item)
+ self.stats.add_number(item)
if self.maximum is None or item > self.maximum:
self.maximum = item
if self.minimum is None or item < self.minimum:
txt += sigma_label.rjust(details.max_label_width)
txt += ' ' * (bar_width - 2)
txt += f'Σ=(100.00% n={self.count})\n'
+ txt += ' ' * (bar_width + details.max_label_width - 2)
+ txt += f'mean(μ)={self.stats.get_mean():.3f}\n'
+ txt += ' ' * (bar_width + details.max_label_width - 2)
+ txt += f'p50(η)={self.stats.get_median():.3f}\n'
+ txt += ' ' * (bar_width + details.max_label_width - 2)
+ txt += f'stdev(σ)={self.stats.get_stdev():.3f}\n'
+ txt += '\n'
return txt