A Histogram helper class. Creates outputs like this::
- [4..5): ▏ ( 0.16% n=1)
- [5..6): ██▍ ( 0.64% n=4)
- [6..7): ██████▏ ( 1.60% n=10)
- [7..8): ████████████▍ ( 3.20% n=20)
- [8..9): █████████████████████▊ ( 5.60% n=35)
- [9..10): ████████████████████████████████▍ ( 8.32% n=52)
- [10..11): ██████████████████████████████████████████▍ (10.88% n=68)
- [11..12): █████████████████████████████████████████████████▉ (12.80% n=80)
- [12..13): ████████████████████████████████████████████████████▉ (13.60% n=85)
- [13..14): █████████████████████████████████████████████████▉ (12.80% n=80)
- [14..15): ██████████████████████████████████████████▍ (10.88% n=68)
- [15..16): ████████████████████████████████▍ ( 8.32% n=52)
- [16..17): █████████████████████▊ ( 5.60% n=35)
- [17..18): ████████████▍ ( 3.20% n=20)
- [18..19): ██████▏ ( 1.60% n=10)
- [19..20): ██▍ ( 0.64% n=4)
- [20..21): ▏ ( 0.16% n=1)
+ [5..6): ▏ ( 0.10% n=1)
+ [6..7): █▋ ( 0.49% n=5)
+ [7..8): █████▏ ( 1.46% n=15)
+ [8..9): ███████████▉ ( 3.42% n=35)
+ [9..10): ██████████████████████▏ ( 6.35% n=65)
+ [10..11): ██████████████████████████████████▌ ( 9.86% n=101)
+ [11..12): ██████████████████████████████████████████████▏ (13.18% n=135)
+ [12..13): ████████████████████████████████████████████████████▉ (15.14% n=155)
+ [13..14): ████████████████████████████████████████████████████▉ (15.14% n=155)
+ [14..15): ██████████████████████████████████████████████▏ (13.18% n=135)
+ [15..16): ██████████████████████████████████▌ ( 9.86% n=101)
+ [16..17): ██████████████████████▏ ( 6.35% n=65)
+ [17..18): ███████████▉ ( 3.42% n=35)
+ [18..19): █████▏ ( 1.46% n=15)
+ [19..20): █▋ ( 0.49% n=5)
+ [20..21): ▏ ( 0.10% n=1)
--------------------------------------------------------------------------------
- [4..21): pop(Σn)=625
- mean(x̄)=12.000
+ [5..21): pop(Σn)=1024
+ mean(μ)=12.500
median(p50)=12.000
mode(Mo)=12.000
- stdev(σ)=0.113
-
+ stdev(σ)=2.500
"""
import math
details.lowest_start = start
if details.highest_end is None or end > details.highest_end:
details.highest_end = end
- label = f'[{label_formatter}..{label_formatter}): ' % (start, end)
+ label = f"[{label_formatter}..{label_formatter}): " % (start, end)
label_width = len(label)
if (
details.max_label_width is None
details.max_label_width = label_width
return details
- def __repr__(self, *, width: int = 80, label_formatter: str = '%d') -> str:
+ def __repr__(self, *, width: int = 80, label_formatter: str = "%d") -> str:
"""Returns a pretty (text) representation of the histogram and
some vital stats about the population in it (min, max, mean,
median, mode, stdev, etc...)
assert details.lowest_start is not None
assert details.highest_end is not None
assert details.max_population is not None
- sigma_label = f'[{label_formatter}..{label_formatter}): ' % (
+ sigma_label = f"[{label_formatter}..{label_formatter}): " % (
details.lowest_start,
details.highest_end,
)
for (start, end), pop in sorted(self.buckets.items(), key=lambda x: x[0]):
if start < details.lowest_start:
continue
- label = f'[{label_formatter}..{label_formatter}): ' % (start, end)
+ label = f"[{label_formatter}..{label_formatter}): " % (start, end)
bar = bar_graph_string(
pop,
details.max_population,
txt += f"({pop/self.count*100.0:5.2f}% n={pop})\n"
if start == details.last_bucket_start:
break
- txt += '-' * width + '\n'
+ txt += "-" * width + "\n"
txt += sigma_label.rjust(details.max_label_width)
- txt += ' ' * (bar_width - 2)
- txt += f' pop(Σn)={self.count}\n'
- txt += ' ' * (bar_width + details.max_label_width - 2)
- txt += f' mean(x̄)={self.stats.get_mean():.3f}\n'
- txt += ' ' * (bar_width + details.max_label_width - 2)
- txt += f' median(p50)={self.stats.get_median():.3f}\n'
- txt += ' ' * (bar_width + details.max_label_width - 2)
- txt += f' mode(Mo)={self.stats.get_mode()[0]:.3f}\n'
- txt += ' ' * (bar_width + details.max_label_width - 2)
- txt += f' stdev(σ)={self.stats.get_stdev():.3f}\n'
- txt += '\n'
+ txt += " " * (bar_width - 2)
+ txt += f" pop(Σ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" median(p50)={self.stats.get_median():.3f}\n"
+ txt += " " * (bar_width + details.max_label_width - 2)
+ txt += f" mode(Mo)={self.stats.get_mode()[0]:.3f}\n"
+ txt += " " * (bar_width + details.max_label_width - 2)
+ txt += f" stdev(σ)={self.stats.get_stdev():.3f}\n"
+ txt += "\n"
return txt