Complete worked example
python
import numpy as np
def inspect_example(labels, hours):
if any(type(label) is not str or not label for label in labels):
raise ValueError("expected normalized non-empty labels")
keys = np.asarray(labels, dtype=np.str_)
values = np.asarray(hours, dtype=np.float64)
if keys.ndim != 1 or keys.shape != values.shape:
raise ValueError("expected aligned vectors")
if not np.isfinite(values).all() or (values < 0).any():
raise ValueError("expected finite nonnegative hours")
unique, inverse, counts = np.unique(keys, return_inverse=True, return_counts=True)
totals = np.bincount(inverse, weights=values, minlength=unique.size)
return {"labels": unique.tolist(), "counts": counts.tolist(), "totals": totals.tolist()}- Reasoning
- The worked function obtains unique labels, inverse codes and counts in one call. It then passes the original hours as weights to bincount, so each weight uses the group code at its original position. The result reports sorted labels, integer observation counts and floating-point totals in the same group order. Distinct synthetic values make incorrect alignments easy to see. Weighted bincount returns numerical totals, not necessarily exact integers for arbitrarily large quantities. This example uses small finite nonnegative hours. Exact money and large counters may need another representation and arithmetic policy. A convenient grouping API does not remove those domain constraints.