Selkie.git | docs/api/ | Selkie--Widget--Histogram.md


NAME
====

Selkie::Widget::Histogram - Bin a numeric series and render it as a BarChart

SYNOPSIS
========

```raku
use Selkie::Widget::Histogram;
use Selkie::Sizing;

# Bin 1000 random samples into 10 bins
my @samples = (1..1000).map: { rand * 100 };
my $h = Selkie::Widget::Histogram.new(
    values => @samples,
    bins   => 10,
    sizing => Sizing.flex,
);

# Custom bin edges instead of equal-width bins
my $edges = Selkie::Widget::Histogram.new(
    values    => @latencies-ms,
    bin-edges => [0, 10, 50, 100, 500, 1000, 5000],
    sizing    => Sizing.flex,
);
```

DESCRIPTION
===========

A histogram is a categorical view of a numeric distribution. This widget bins a list of numeric values into intervals and delegates rendering to [Selkie::Widget::BarChart](Selkie--Widget--BarChart.md). Each bin becomes a bar labelled by its lower edge.

Bin convention
--------------

Intervals are **left-closed, right-open**, with the final bin **closed-closed** so the maximum sample is always counted. For bin edges `[0, 10, 20, 30]`:

  * Bin 1: `[0, 10)` — values 0 ≤ v < 10

  * Bin 2: `[10, 20)`

  * Bin 3: `[20, 30]` — values 20 ≤ v ≤ 30 (inclusive)

This matches numpy / R / matplotlib defaults.

Modes
-----

Two ways to specify the bins:

  * **Equal-width** — pass `:bins(N)`. The widget computes N equal-width bins spanning `[min, max]` of the data.

  * **Explicit edges** — pass `:bin-edges([...])`. The widget uses your edges directly. `edges.elems` = bin count + 1.

The two are mutually exclusive. `:bins` is convenient; `:bin-edges` is for non-uniform binning (log-scale latency, age brackets, etc.).

EXAMPLES
========

Distribution of request latencies
---------------------------------

```raku
my @latencies = $request-log.map: *.<duration-ms>;
my $h = Selkie::Widget::Histogram.new(
    values => @latencies,
    bins   => 20,
    sizing => Sizing.flex,
);
```

Non-uniform bins for skewed data
--------------------------------

Latencies cluster near zero with a long tail. Equal bins waste most of the chart on near-zero values. Custom edges let you focus on the distribution where it matters:

```raku
my $h = Selkie::Widget::Histogram.new(
    values    => @latencies,
    bin-edges => [0, 5, 10, 25, 50, 100, 250, 500, 1000, 5000],
    sizing    => Sizing.flex,
);
```

Reactive — auto-rebin when the source data changes
--------------------------------------------------

```raku
# Histogram doesn't bind to a store directly; instead, subscribe in
# app code and call set-values when the source updates.
$store.subscribe-with-callback(
    'latencies-hist',
    -> $s { $s.get-in('metrics', 'latency-samples') // [] },
    -> @samples { $hist.set-values(@samples) },
    $hist,
);
```

SEE ALSO
========

  * [Selkie::Widget::BarChart](Selkie--Widget--BarChart.md) — the bar renderer this delegates to

  * [Selkie::Plot::Ticks](Selkie--Plot--Ticks.md) — for picking nice bin edges manually

### has Positional[Real] @.values

Numeric values to bin.

### has UInt $.bins

Equal-width bin count. Mutually exclusive with `bin-edges`.

### has Positional[Real] @.bin-edges

Explicit bin edges, ascending. `bin-edges.elems` = bin count + 1. Mutually exclusive with `bins`.

### method set-values

```raku
method set-values(
    @new
) returns Mu
```

Replace the value list and re-bin. The chart re-renders automatically.