@kanaries/ml
Guides

IQR vs Z-Score vs Isolation Forest: Compare the Same Dataset

See why a robust fence, a mean-based score and a multivariate anomaly detector can disagree, with a reproducible CSV example.

View as Markdown

Different anomaly rules answer different questions. IQR measures distance beyond the middle half of a single column. Z-scores measure distance from its mean in standard-deviation units. Isolation Forest asks how easily a record can be separated from other records across the supplied features.

Run two rules on the same observations

Load the example in the outlier calculator. Its values are 10, 11, 12, 12, 13, 14, 15, 16, 17 and 80. IQR flags 80: the upper fence is 21.375. Switch to Z-score and calculate again. With the population standard deviation and a strict absolute threshold above 3, it flags no rows. The largest Z-score is about 2.98.

That disagreement is expected. The value 80 pulls the mean upward and inflates the standard deviation used to judge itself. In a sample of ten observations, the maximum possible population Z-score is at most the square root of nine, or 3. A strict threshold above 3 cannot flag an observation in this sample. More data or a different rule is required; repeatedly adjusting a threshold until one preferred row is flagged is a weak validation procedure.

Compare assumptions before counts

MethodInput and ruleUseful starting pointMain limitation
IQROne column; outside Q1/Q3 by 1.5 times IQRSkewed numeric data and quick reviewCannot detect unusual feature combinations
Z-scoreOne column; absolute population Z above 3Roughly symmetric data with meaningful mean and spreadExtreme values alter both mean and spread
Modified Z-scoreOne column; median/MAD score above 3.5A robust alternative to the meanUndefined when MAD is zero
Isolation ForestOne or more features; fitted anomaly scoresUnusual combinations of numeric featuresDepends on sampling, seed, features and threshold

Fit Isolation Forest to those same ten values

The following JavaScript uses the identical observations, 100 trees, a subsample of ten, seed 42 and contamination 0.1. Run it with @kanaries/ml in Node.js or a browser bundler.

import { Ensemble } from '@kanaries/ml';

const values = [10, 11, 12, 12, 13, 14, 15, 16, 17, 80];
const X = values.map(value => [value]);
const model = new Ensemble.IsolationForest(10, 100, 0.1, 42);
model.fit(X);
console.log(model.predict(X));
// [0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
console.log(X.map(row => model.anomalyScore(row)));

With the published version used by this site, 80 has the highest anomaly score, approximately 0.807, and is the only flagged value. IQR and this forest agree here; the strict 3σ rule flags none. Contamination 0.1 is an explicit threshold choice for this demonstration, not evidence that ten percent of future records will be anomalous. This small example checks behavior; it does not establish which detector is best on real data.

Add a second feature when the question requires it

An order of 80 units may be ordinary for an account that usually buys 100 units and unusual for an account that buys one. A univariate quantity fence has no access to that context. Include a relevant historical feature, then compare the joint pattern with an Isolation Forest model.

The JavaScript Isolation Forest guide provides a separate interactive model, explains contamination, and includes implementation examples. The CSV calculator implements the three statistical rules above; it does not silently substitute Isolation Forest. Use the guide's implementation for a controlled model comparison on your own matrix. Fix the seed, list the features and record the threshold alongside flagged row IDs.

Validate labels and outcomes

The @kanaries/ml Isolation Forest API labels anomalies as 1 and normal records as 0. Scikit-learn's predict labels outliers as -1 and inliers as 1. Translate these conventions before comparing model outputs. Otherwise identical detections can look completely different.

Prefer a reviewed set of incidents to a target anomaly percentage. If you have no labels, inspect examples from several score ranges, repeat the fit with different seeds, and ask whether the findings support a useful action. A method that flags fewer rows is not automatically more accurate. See the CSV review workflow for retaining and investigating original records.