mirror of
https://github.com/lexmount/moli.git
synced 2026-09-28 16:01:39 +00:00
40 lines
1.1 KiB
Python
40 lines
1.1 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Iterable
|
|
|
|
|
|
def percentile(values: Iterable[float], percent: float) -> float | None:
|
|
ordered = sorted(float(value) for value in values)
|
|
if not ordered:
|
|
return None
|
|
if len(ordered) == 1:
|
|
return ordered[0]
|
|
rank = (len(ordered) - 1) * (percent / 100.0)
|
|
lower = int(rank)
|
|
upper = min(lower + 1, len(ordered) - 1)
|
|
weight = rank - lower
|
|
return ordered[lower] * (1.0 - weight) + ordered[upper] * weight
|
|
|
|
|
|
def summarize(values: Iterable[float]) -> dict[str, float | int | None]:
|
|
ordered = sorted(float(value) for value in values)
|
|
if not ordered:
|
|
return {
|
|
"count": 0,
|
|
"min": None,
|
|
"max": None,
|
|
"median": None,
|
|
"p50": None,
|
|
"p90": None,
|
|
"p95": None,
|
|
}
|
|
return {
|
|
"count": len(ordered),
|
|
"min": ordered[0],
|
|
"max": ordered[-1],
|
|
"median": percentile(ordered, 50),
|
|
"p50": percentile(ordered, 50),
|
|
"p90": percentile(ordered, 90),
|
|
"p95": percentile(ordered, 95),
|
|
}
|