Skip to content

HistogramBins

Mojo struct 🡭

HistogramBins

@memory_only
struct HistogramBins

A binned sample: len(edges) - 1 bins, edges ascending, one entry in values per bin. What histogram_bins() returns and what histogram() draws.

Numeric edges rather than the List[String] range labels this module stored before. A label like "52.0-57.8" is a formatted view of a number, and every downstream use – placing a bar over the interval it actually covers, sharing an x-domain with a density curve, aligning a marginal histogram with the joint plot it sits beside – needs the number back. Rounding it to one decimal place for display and then parsing it again would be a lossy round trip through a string for no reason.

edges is bins + 1 long, not one (lo, hi) pair per bin, because a histogram’s bins tile an interval with no gaps and no overlaps: the pair form can express a gap or an overlap, which is a state nothing here can draw and every consumer would have to check for. Unequal widths are fine – the shared edge is exactly what makes them still a tiling.

Fields

  • edges (List[Float64]): The bins + 1 bin boundaries, strictly ascending. Bin i covers [edges[i], edges[i + 1]), except the last, which includes edges[-1].
  • values (List[Float64]): One value per bin, in HistStat’s units.

Implemented traits

AnyType, Copyable, Deinitable, Movable, Sized

Methods

__init__

fn def __init__(out self, var edges: List[Float64], var values: List[Float64])

Construct directly from already-computed columns.

Args:

  • edges (List[Float64]): The bins + 1 boundaries, strictly ascending.
  • values (List[Float64]): One value per bin.
  • self (Self)

Returns:

Self

__len__

fn def __len__(self) -> Int

How many bins there are.

Args:

  • self (Self)

Returns:

Int: len(edges) - 1.

width

fn def width(self, i: Int) -> Float64

Bin i’s width.

Args:

  • self (Self)
  • i (Int): Bin index, 0 through len(self) - 1.

Returns:

Float64: edges[i + 1] - edges[i].

center

fn def center(self, i: Int) -> Float64

Bin i’s midpoint – where a marker or a label for the bin goes.

Computed as lo + (hi - lo) / 2 rather than (lo + hi) / 2: the two agree to a rounding step for ordinary data, but the sum form overflows to infinity for edges near Float64’s maximum and the difference form does not.

Args:

  • self (Self)
  • i (Int): Bin index, 0 through len(self) - 1.

Returns:

Float64: The midpoint of [edges[i], edges[i + 1]].

total

fn def total(self) -> Float64

The sum of every bin’s value – W for COUNT, 1.0 for PROBABILITY, 100.0 for PERCENT, and a number with no meaning of its own for the two width-normalized stats (sum value[i] * width[i] for those instead).

Args:

  • self (Self)

Returns:

Float64: sum(values).

step_x

fn def step_x(self) -> List[Float64]

The x column for drawing this as a staircase: every edge, in order, bins + 1 long. Pair with step_y() and mark_area(step=StepStyle.POST) (or mark_line), which is exactly what histogram() does.

POST is the style that matches: it holds y[i] across [x[i], x[i + 1]), which is the half-open bin [edges[i], edges[i + 1]). PRE would draw every bar shifted one bin left and MID half a bin left.

Args:

  • self (Self)

Returns:

List[Float64]: A copy of edges.

step_y

fn def step_y(self) -> List[Float64]

The y column for step_x(): every bin’s value, plus the last value repeated so the final plateau has a point to run out to at edges[-1].

StepStyle.POST draws [x[i], x[i + 1]) at y[i] and stops at the last sample, so without the repeat the rightmost bin would be a bar with no top.

Args:

  • self (Self)

Returns:

List[Float64]: values with values[-1] appended, bins + 1 long.