Functional Weave
Code in TypeScript

charts.histogram-bins@1.0.0

README.md

2,273 bytes · view raw

# charts.histogram-bins

Sorts a sample into histogram bins with round edges:
`histogramBins([1..10], "sturges", null)` gives five bins, 0-2, 2-4, ..., 8-10.
Each bin counts values with `x0 <= v < x1`; the last bin also counts its right
edge, so the maximum is never lost off the end.

## How many bins

- **`sturges`**: ceil(log2 n) + 1 bins (Sturges 1926), d3.bin's default. It
  assumes a roughly normal sample and gives too few bins for large or skewed
  ones. log2 is found by doubling, not with a logarithm.
- **`freedman-diaconis`**: bin width 2 x IQR x n^(-1/3) (Freedman and
  Diaconis 1981), which follows the middle half of the data and so is not
  stretched by an outlier. The quartiles are `stats.percentile` with the
  `linear` method (R-7, as d3's quantile), and n^(-1/3) is `math.pow`. When the
  interquartile range is zero it falls back to one bin, as d3 does.
- **`fixed-width`**: the width you pass, with edges on its multiples (a width
  of 5 puts edges on ..., -5, 0, 5, 10, ...). `binWidth` must be null for the
  other two methods: an argument that would be silently ignored is an error.

For the first two, the count is turned into a round width with `charts.ticks`
(1, 2 or 5 x 10^k for about that many bins), as d3.bin does with its nice
thresholds, so edges fall on numbers a reader expects rather than on
min + k x (max - min) / count.

## Edges

The first edge is the multiple of the width at or below the minimum and the
last the first at or above the maximum. Each edge is one exact operation on a
whole number (i x width, or i / divisor for a fractional round width) and is
then cleaned at 12 decimal places with `math.round-float`, so a width of 0.1
has an edge at 0.3, not 0.30000000000000004 as `3 * 0.1` gives, and a value of
exactly 0.3 lands in the bin starting there.

No values gives no bins; values that are all equal give one bin of no width
under the first two methods. More than 10,000 bins is an error.

Sources: H. A. Sturges, "The Choice of a Class Interval", Journal of the
American Statistical Association 21 (1926) 65-66; D. Freedman and P.
Diaconis, "On the histogram as a density estimator: L2 theory", Zeitschrift
für Wahrscheinlichkeitstheorie 57 (1981) 453-476; Mike Bostock, d3-array
`bin.js` and `threshold/*.js`.