Lattice Grid Buy a licence

developer guide

Statistics, capability and intervals

What the grid knows about its own numbers: column profiling, process control and capability, confidence intervals, and the tiles that put a figure above the table.

Developer guide › Statistics, capability and intervals

Profiling and statistics

grid.statistics answers questions about the rows the filters left, so every figure describes what the user is looking at rather than the whole table.

Everything worth knowing about a column, in one pass

const p = grid.statistics.profile('capacity');

p.count; p.missing; p.distinct;
p.min; p.q1; p.median; p.q3; p.max;
p.mean; p.stdDev;
p.outliers;      // by the interquartile rule
p.histogram;     // bins, ready to draw
p.alerts;        // what is worth looking at

alerts is the part that saves time: a column that never varies, a key that turns out not to be unique, a fifth of the rows missing. A profile that reports only numbers leaves the reader to notice those, and readers reliably do not.

MethodAnswers
reduceA column through any of the thirty-eight named kernels, or one of your own.
correlationPearson's r between two columns. spearman resists an outlier; kendall is tau-b.
regressionA least-squares fit of one column on another, with slope, intercept and r².
weightedAverageOne column averaged by another. weightedQuantile for the median and beyond.
seriesHow a column varies along an ordering. by is required and never guessed.
shadowWhat the grid knows about a row over time: updates, delta, rate, rank, percentile, streak.

The filters are part of the question. Every one of these reads the filtered rows. Narrow the grid and the statistics narrow with it, which is the behaviour you want when the filter is the analysis.

Kernels see arrival order, not display order. Anything order-dependent takes an explicit by rather than inferring one from the current sort, so the answer does not change when a user clicks a column header.

Process control and capability

Whether a process sits inside the tolerance it was given, and whether it is behaving or drifting. The tolerance is declared once, on the column.

The specification lives with the column

{ id: 'diameter', type: 'number', spec: { lower: 9.95, upper: 10.05, target: 10 } }

Asking for the capability

const c = grid.statistics.capability('diameter', { rules: 'nelson' });

c.cp; c.cpk;         // short-term spread, from the moving range
c.pp; c.ppk;         // overall spread
c.outOfSpec;         // parts outside the customer's tolerance
c.limits;            // { centre, upper, lower, sigma }
c.violations;        // [{ index, rule, description }, …]
c.interval;          // a confidence interval for cpk

One declared tolerance, so nothing can disagree. The indices, the charts and any conditional format all read the same spec. A tolerance passed separately to each is a tolerance that eventually differs between them, and a capability report that contradicts the cell colouring is worse than neither.

Cp and Cpk use short-term variation, Pp and Ppk overall. The first pair comes from the moving range, which is what the process can do when it is behaving; the second from the whole spread, which is what it actually delivered. Ppk well below Cpk is the signal that the process drifted rather than that it is incapable.

A baseline finds a shift instead of absorbing it. baseline: 30 fixes the limits over the first thirty readings. Limits recomputed over all the data widen to accommodate the very shift you are looking for, and then report no violation.

The point estimate alone overstates the case. A Cpk of 1.35 measured on thirty parts has a lower bound below 1.0, so a process that has "passed" a 1.33 requirement on thirty parts has demonstrated very little. interval is reported alongside it for that reason.

Drawing it

Three chart types complete the picture, and they read the same specification.

TypeShows
controlReadings against the centre line and control limits, with every rule break numbered.
movingRangeThe companion chart: variation between consecutive readings.
capabilityThe distribution against the tolerance, with a curve for each of the two spreads.

Rule breaks are numbered rather than merely marked, under Western Electric's four rules or Nelson's eight. The two sets number differently, so the chart names which it applied: a "rule 3" that could mean either is not a finding anyone can act on.

Confidence intervals

How firmly the data pins a figure down. An interval narrows as the grid does, because it describes the filtered rows and not the whole table.

A mean and a rate

grid.statistics.interval('capacity');
// { lower, upper, mean, n, confidence }, by Student's t

grid.statistics.interval('status', {
  kind: 'proportion',
  where: (v) => v === 'failed',
});
// Wilson score, which stays sensible at small n and near 0 or 1

Intervals are also available on a regression slope and on a capability index. Each uses the method that suits it: Student's t for a mean, the Wilson score for a proportion, and Bissell's approximation for Cpk.

The line the product draws. Lattice quantifies uncertainty. It does not adjudicate hypotheses: there are no p-values and no significance tests. An interval says how precisely a figure is known and leaves the judgement where it belongs. A tool that returns a verdict invites it to be read as one, and a grid is the wrong place for that.

Wilson, not the textbook formula. The normal approximation gives bounds below zero and above one at small counts, which is visibly wrong to anyone who reads it. The Wilson score stays inside the interval it is describing.

Statistic tiles

A headline figure over a grid, with the change since a baseline, a tone from thresholds, and the interval underneath.

A tile that follows the grid

import { createStat } from '@toclocoinc/lattice-grid';

createStat({
  grid,
  container: tile,
  title: 'Total capacity',
  value: { of: 'capacity', fn: 'sum' },
  baseline: (g) => lastMonth,
  bands: { good: 5000, warn: 3000, direction: 'up' },
  interval: (v, g) => g.statistics.interval('capacity'),
});

bands and goodWhen judge different things. goodWhen says whether a rise is good news, and colours the change indicator. bands judge the value itself. They are separate because a Cpk of 0.9 is bad news whether it rose or fell to get there.

The tile follows the grid by default. Filter the grid and the figure updates. scope chooses filtered, all or selected rows; live: false detaches it and leaves refresh() to you.

value also takes show, which reports a field from the row holding an extreme rather than the extreme itself: { of: 'sales', fn: 'max', show: 'rep' } is the name of the best rep. It needs min or max, because no single row holds an average.