summarise_cases

summarise_cases(rows)

Turn per-case rows into the distribution, one row per metric.

What a paper reports: not a single Dice, but its mean, its spread and its worst case. The minimum is the one nobody publishes and everybody should - a model averaging 0.86 that scores 0.11 on some patient has a failure mode, and the mean is where it hides.

Standard deviation is the sample one (n-1), and is None for a single case, because the spread of one number is not zero, it is unknown.

Parameters

Name Type Description Default
rows list[dict[str, Any]] One dict per case, as Engine.evaluate_cases returns - a case column naming it, or group when the rows were pooled by group_by, and a float column per metric. Columns that are not floats are passed over. required

Returns

Name Type Description
list[dict[str, Any]] One dict per metric, with metric, n, mean, sd, median, min, max
list[dict[str, Any]] and worst_case - or worst_group when the rows were grouped, because naming
list[dict[str, Any]] it worst_case there would describe the wrong thing.

Raises

Name Type Description
EngineError If there are no rows, or no column is a float - “nothing to summarise” and “nothing here is a number” are different problems.

rows = [ … {“case”: “patient01”, “dice”: 0.91}, … {“case”: “patient02”, “dice”: 0.88}, … {“case”: “patient03”, “dice”: 0.11}, … ] summary = summarise_cases(rows)[0] summary[“metric”], summary[“n”] (‘dice’, 3) round(summary[“mean”], 3), summary[“min”], summary[“worst_case”] (0.633, 0.11, ‘patient03’)

The mean is 0.63 and one case sits at 0.11, which is the argument for reporting the minimum: over a hundred cases the mean hides it completely.

Grouped rows are named for what they are:

grouped = [{“group”: “p01”, “dice”: 0.9}, {“group”: “p02”, “dice”: 0.4}] sorted(summarise_cases(grouped)[0])[-1] ‘worst_group’

The spread of one number is unknown rather than zero:

summarise_cases([{“case”: “only”, “dice”: 0.9}])[0][“sd”] is None True