Skip to content

@absoluteui/helpers/stats

Mean, median, percentiles, deviation, histograms, correlation, and regression.

import { ... } from '@absoluteui/helpers/stats';

Descriptive statistics for dashboards and reports: averages, percentiles, spread, outliers, histograms, trends, and simple regression. Functions return undefined for empty input rather than NaN, and reject NaN/Infinity unless you pass nonFinite: 'ignore'. Percentiles match Excel PERCENTILE.INC by default, and variance is the sample statistic (VAR.S) unless population: true. The Charts guide shows how to plot the results.

Median and quartiles describe a pay band better than the mean, which a few high earners pull up.

import { mean, median, percentile, quartiles } from '@absoluteui/helpers/stats';
const salaries = [42_000, 45_000, 47_500, 48_000, 51_000, 53_000, 55_500, 120_000];
mean(salaries); // => 57750
median(salaries); // => 49500
quartiles(salaries); // => [46875, 49500, 53625]
percentile(salaries, 90); // => ≈ 74850

outliers applies Tukey fences (k: 1.5 by default, 3 for “far out”) and returns the input indexes, so you can point back to the employees.

import { outliers } from '@absoluteui/helpers/stats';
const team = [
{ name: 'Asha', hours: 4 }, { name: 'Ben', hours: 6 }, { name: 'Chen', hours: 5 },
{ name: 'Dana', hours: 7 }, { name: 'Eli', hours: 31 }, { name: 'Fay', hours: 5 },
];
const result = outliers(team.map((e) => e.hours));
result?.indexes.map((i) => team[i]?.name); // => ['Eli']
result?.upperFence; // => 9.375

How do I bucket values for a distribution chart?

Section titled “How do I bucket values for a distribution chart?”

histogram returns bins with inclusive lower and exclusive upper edges; binWidth aligns edges to round numbers such as ten-year age bands.

import { histogram } from '@absoluteui/helpers/stats';
const ages = [23, 27, 29, 31, 34, 35, 38, 41, 44, 52];
histogram(ages, { binWidth: 10 }).map((b) => `${b.x0}–${b.x1 - 1}: ${b.count}`); // => ['20–29: 3', '30–39: 4', '40–49: 2', '50–59: 1']

How do I smooth a monthly trend and project it forward?

Section titled “How do I smooth a monthly trend and project it forward?”

movingAverage smooths noise; linearRegression fits a straight line and predict extends it. Treat projections as indicative only.

import { linearRegression, movingAverage } from '@absoluteui/helpers/stats';
const headcount = [120, 124, 123, 129, 133, 136];
movingAverage(headcount, 3); // => [122.33333333333333, 125.33333333333333, 128.33333333333334, 132.66666666666666]
const fit = linearRegression([1, 2, 3, 4, 5, 6], headcount);
fit === undefined ? undefined : Math.round(fit.predict(9)); // => 145

Empty input gives undefined, and non-finite values (often a failed parse upstream) throw unless you opt in to skipping them:

import { mean } from '@absoluteui/helpers/stats';
mean([]); // => undefined
mean([5, Number.NaN, 7]); // => throws HLP_STATS_NOT_FINITE
mean([5, Number.NaN, 7], { nonFinite: 'ignore' }); // => 6

correlation

Pearson correlation in [-1, 1]; undefined for fewer than 2 pairs or a constant series.

function correlation(xs: readonly number[], ys: readonly number[], options?: StatsOptions): number | undefined;

Example:

correlation([1, 2, 3], [3, 2, 1]) // => -1

covariance

Covariance of paired series (sample by default).

function covariance(xs: readonly number[], ys: readonly number[], options?: VarianceOptions): number | undefined;

Example:

covariance([1, 2, 3], [2, 4, 6]) // => 2

cumulativeSum

Running totals (compensated).

function cumulativeSum(values: readonly number[], options?: StatsOptions): number[];

Example:

cumulativeSum([0.1, 0.2, 0.3]) // => [0.1, 0.30000000000000004, 0.6] // naive running addition ends at 0.6000000000000001

extent

[min, max] in one pass (no spread, safe for huge arrays).

function extent(values: readonly number[], options?: StatsOptions): [number, number] | undefined;

Example:

extent([3, 1, 4]) // => [1, 4]

frequencies

Occurrence counts in first-seen order (a Map, so any value type is safe as a key).

function frequencies<T>(values: Iterable<T>): Map<T, number>;

Example:

frequencies(['a', 'b', 'a']) // => new Map([['a', 2], ['b', 1]])

geometricMean

Geometric mean of non-negative values (0 if any is 0); undefined if any is negative.

function geometricMean(values: readonly number[], options?: StatsOptions): number | undefined;

Example:

geometricMean([1, 4, 16]) // => 4

harmonicMean

Harmonic mean of non-negative values (0 if any is 0); undefined if any is negative.

function harmonicMean(values: readonly number[], options?: StatsOptions): number | undefined;

Example:

harmonicMean([1, 4, 4]) // => 2

histogram

Equal-width histogram.

function histogram(values: readonly number[], options?: HistogramOptions): HistogramBin[];

Example:

histogram([1, 2, 2, 3, 9], { bins: 2 }) // => [{ x0: 1, x1: 5, count: 4 }, { x0: 5, x1: 9, count: 1 }]

iqr

Interquartile range Q3 - Q1.

function iqr(values: readonly number[], options?: PercentileOptions): number | undefined;

Example:

iqr([1, 2, 3, 4, 5]) // => 2

kurtosis

Excess kurtosis: sample-adjusted (Excel KURT, n >= 4) by default, or population g2.

function kurtosis(values: readonly number[], options?: VarianceOptions): number | undefined;

Example:

kurtosis([1, 2, 3, 4]) // => ≈ -1.2

linearRegression

Ordinary least squares fit y = slope|x + intercept; undefined for < 2 pairs or constant x.

function linearRegression(xs: readonly number[], ys: readonly number[], options?: StatsOptions): LinearRegression | undefined;

Example:

linearRegression([1, 2, 3], [2, 4, 6])?.predict(4) // => 8

mean

Arithmetic mean.

function mean(values: readonly number[], options?: StatsOptions): number | undefined;

Example:

mean([1, 2, 3, 4]) // => 2.5

median

Median (mean of the two middle values for even counts).

function median(values: readonly number[], options?: StatsOptions): number | undefined;

Example:

median([3, 1, 4, 2]) // => 2.5

mode

All most-frequent values, ascending (several for multi-modal data).

function mode(values: readonly number[], options?: StatsOptions): number[] | undefined;

Example:

mode([1, 2, 2, 3, 3]) // => [2, 3]

movingAverage

Trailing simple moving average; result has length - window + 1 entries (empty when window > length).

function movingAverage(values: readonly number[], window: number, options?: StatsOptions): number[];

Example:

movingAverage([1, 2, 3, 4], 2) // => [1.5, 2.5, 3.5]

normalize

Min-max scaling to [0, 1]; a constant series maps to all zeros.

function normalize(values: readonly number[], options?: StatsOptions): number[] | undefined;

Example:

normalize([10, 15, 20]) // => [0, 0.5, 1]

outliers

Tukey fences [Q1 - k|IQR, Q3 + k|IQR] and the values outside them.

function outliers(values: readonly number[], options?: OutlierOptions): OutlierResult | undefined;

Example:

outliers([1, 2, 3, 4, 100])?.outliers // => [100]

percentile

Percentile for p in [0, 100].

function percentile(values: readonly number[], p: number, options?: PercentileOptions): number | undefined;

Example:

percentile([1, 2, 3, 4, 5], 90) // => 4.6 // Excel PERCENTILE.INC

quantile

Quantile for q in [0, 1] (same methods as percentile).

function quantile(values: readonly number[], q: number, options?: PercentileOptions): number | undefined;

Example:

quantile([1, 2, 3, 4], 0.25) // => 1.75

quantiles

The n - 1 cut points dividing the data into n equal-probability groups (n in 2..1000).

function quantiles(values: readonly number[], n: number, options?: PercentileOptions): number[] | undefined;

Example:

quantiles([1, 2, 3, 4, 5], 4) // => [2, 3, 4]

quartiles

[Q1, median, Q3] (linear method).

function quartiles(values: readonly number[], options?: PercentileOptions): [number, number, number] | undefined;

Example:

quartiles([1, 2, 3, 4, 5]) // => [2, 3, 4]

rangeOf

Range max - min (named rangeOf to avoid clashing with the array module’s range).

function rangeOf(values: readonly number[], options?: StatsOptions): number | undefined;

Example:

rangeOf([3, 1, 4]) // => 3

skewness

Skewness: sample-adjusted (Excel SKEW, n >= 3) by default, or population g1.

function skewness(values: readonly number[], options?: VarianceOptions): number | undefined;

Example:

skewness([1, 2, 3]) // => 0

standardize

Z-scores of every value (sample standard deviation unless population). undefined when constant.

function standardize(values: readonly number[], options?: VarianceOptions): number[] | undefined;

Example:

standardize([1, 2, 3]) // => [-1, 0, 1]

stdDev

Standard deviation (sample by default).

function stdDev(values: readonly number[], options?: VarianceOptions): number | undefined;

Example:

stdDev([2, 4, 4, 4, 5, 5, 7, 9], { population: true }) // => 2

variance

Variance (sample by default; population: true for n). Sample variance needs >= 2 values.

function variance(values: readonly number[], options?: VarianceOptions): number | undefined;

Example:

variance([2, 4, 4, 4, 5, 5, 7, 9], { population: true }) // => 4

weightedMean

Weighted mean; weights must be finite and non-negative. undefined when all weights are 0.

function weightedMean(values: readonly number[], weights: readonly number[], options?: StatsOptions): number | undefined;

Example:

weightedMean([80, 90], [1, 3]) // => 87.5

zScore

Standard score (value - mean) / stdDev; undefined when stdDev is 0.

function zScore(value: number, meanValue: number, stdDevValue: number): number | undefined;

Example:

zScore(130, 100, 15) // => 2

MAX_HISTOGRAM_BINS

Largest bin count histogram produces.

const MAX_HISTOGRAM_BINS = 10000;

HistogramBin

interface HistogramBin {
readonly x0: number;
readonly x1: number;
readonly count: number;
}

HistogramOptions

interface HistogramOptions extends StatsOptions {
readonly bins?: number;
readonly binWidth?: number;
readonly domain?: readonly [number, number];
}

LinearRegression

interface LinearRegression {
readonly slope: number;
readonly intercept: number;
readonly r2: number;
predict(x: number): number;
}

OutlierOptions

interface OutlierOptions extends StatsOptions {
readonly k?: number;
}

OutlierResult

interface OutlierResult {
readonly lowerFence: number;
readonly upperFence: number;
readonly outliers: number[];
readonly indexes: number[];
}

PercentileOptions

interface PercentileOptions extends StatsOptions {
readonly method?: PercentileMethod;
}

StatsOptions

interface StatsOptions {
readonly nonFinite?: 'throw' | 'ignore';
}

VarianceOptions

interface VarianceOptions extends StatsOptions {
readonly population?: boolean;
}

PercentileMethod

Percentile interpolation methods (NumPy names); linear equals Excel PERCENTILE.INC.

type PercentileMethod = 'linear' | 'nearest' | 'lower' | 'higher' | 'midpoint';