UNPKG

ts-scikit

Version:

A scientific toolkit written in Typescript

210 lines 6.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Histogram = void 0; const utils_1 = require("../utils"); const sampling_1 = require("./sampling"); /** * A histogram. * <p> * A histogram summarizes the distribution of values v in an array. * The range (vmax - vmin) of values v in the array is partitioned uniformly * into some number of bins. Each bin then contains the number of values * that lie closest to the center of that bin. * <p> * If the values v in the array are assumed to be instances of some random * variable, then a probability density function may be estimated for that * variable by simply dividing the count in each bin by the total number of * values in that array. The resulting functions are called the densities. * <p> * The number of bins may be specified or computed automatically. In the * automatic case, we compute bin width as: * <pre><code> * w = 2.0 * (v75 - v25) / pow(n, 1.0/3.0), * </code></pre> * where n denotes the number of values, and v25 and v75 are the 25th and * 75th percentiles, respectively. The number of bins is then computed by * dividing the range (vmax - vmin) of values by that bin width, rounding * down to the nearest integer. In this way, the number of bins grows * as the cube root of the number of values n. * <p> * Minimum and maximum values (vmin and vmax) may also be specified or * computed automatically. If specified, then only the values in the range * [vmin, vmax] are binned, and values outside this range are ignored. * <p> * Reference: Izenman, A. J., 1991, Recent developments in nonparametric * density estimation: Journal of the American Statistical Association, * v. 86, p. 205-224. */ class Histogram { /** * Constructs a new histogram. * <p> * The min and max bin values are computed automatically, unless the user * provides a min and max value. * @param v an array of numbers. * @param nbin the number of bins. * @param vmin the minimum value (optional). * @param vmax the maximum value (optional). */ constructor(v, nbin, vmin, vmax) { this.initMinMax(v, vmin, vmax); this.init(v, nbin); } /** * Gets the min value. */ get min() { return this._vmin; } /** * Gets the max value. */ get max() { return this._vmax; } /** * Gets the bin count. */ get binCount() { return this._sbin.count; } /** * Gets the bin delta. */ get binDelta() { return this._sbin.delta; } /** * Gets the first bin value. */ get binFirst() { return this._sbin.first; } /** * Gets the bin sampling. */ get binSampling() { return this._sbin; } /** * Gets the counts. */ get counts() { return Object.assign({}, this._h); } /** * Gets the count of values in the range. */ get inCount() { return this._nin; } /** * Gets the count of values too low. */ get lowCount() { return this._nlo; } /** * Gets the count of values too high. */ get highCount() { return this._nhi; } /** * Gets the densities. */ get densities() { const nbin = this.binCount; const d = new Array(nbin); const s = 1.0 / this._nin; for (let ibin = 0; ibin < nbin; ++ibin) { d[ibin] = s * this._h[ibin]; } return d; } /** * Initializes the histogram. If nbin is zero, then this method computes * the number of bins. */ init(v, nbin) { let dbin = (this._vmax - this._vmin) / Math.max(1, nbin); if (dbin === 0.0) { dbin = Math.max(1.0, 2.0 * Math.abs(this._vmin) * Number.EPSILON); } if (nbin === 0) { // Must have at least one bin... nbin = 1; if (this._vmin < this._vmax) { const t = this.trim(v); const n = t.length; if (n > 0) { const k25 = Math.round(0.25 * (n - 1)); utils_1.quickPartialSort(k25, t); const v25 = t[k25]; const k75 = Math.round(0.75 * (n - 1)); utils_1.quickPartialSort(k75, t); const v75 = t[k75]; if (v25 < v75) { dbin = 2.0 * (v75 - v25) * Math.pow(n, -1.0 / 3.0); nbin = Math.max(1, Math.floor((this._vmax - this._vmin) / dbin)); dbin = (this._vmax - this._vmin) / nbin; } } } } const fbin = this._vmin + 0.5 * dbin; this._sbin = new sampling_1.Sampling(nbin, dbin, fbin); // Count binned values. const vscl = 1.0 / dbin; const n = v.length; this._nlo = 0; this._nhi = 0; this._h = new Array(nbin).fill(0); this._nin = 0; for (let i = 0; i < n; ++i) { const vi = v[i]; if (vi < this._vmin) { this._nlo += 1; } else if (vi > this._vmax) { this._nhi += 1; } else { let ibin = Math.round((vi - fbin) * vscl); if (ibin < 0) { ibin = 0; } else if (ibin >= nbin) { ibin = nbin - 1; } this._h[ibin] += 1; this._nin += 1; } } } initMinMax(v, vmin, vmax) { if (vmin && vmax) { utils_1.Check.argument(vmin <= vmax, 'vmin <= vmax'); this._vmin = vmin; this._vmax = vmax; this._computedMinMax = false; } else { const n = v.length; this._vmin = this._vmax = v[0]; for (let i = 1; i < n; ++i) { const vi = v[i]; if (vi < this._vmin) { this._vmin = vi; } if (vi > this._vmax) { this._vmax = vi; } } this._computedMinMax = true; } } trim(v) { let t; if (this._computedMinMax) { t = Object.assign([], v); } else { const n = v.length; t = new Array(n); let m = 0; for (let i = 0; i < n; ++i) { const vi = v[i]; if (this._vmin <= vi && vi <= this._vmax) { t[m++] = vi; } } if (m < n) { t = utils_1.copy(t, m); } } return t; } } exports.Histogram = Histogram; //# sourceMappingURL=histogram.js.map