Skip to content

Scatter anomaly detection ​

Everything described elsewhere in these docs — executeAnomalyDetection, useAnomalyDetection, DatastripesAnomaly, z-score/IQR/MAD/STL/ensemble — assumes your data is an ordered time series: one value per timestamp.

Not all anomaly detection is like that. If your data is a scatter of two independent metrics (e.g. CPU vs. memory, price vs. volume, latency vs. error rate) with no meaningful order, a time-series method doesn't apply: a point can be perfectly normal on each axis individually and still be an outlier in the combination of the two.

For that case, Datastripes ships a parallel, self-contained API:

  • executeScatterAnomalyDetection(options) — the core function, analogous to executeAnomalyDetection
  • useScatterAnomalyDetection(options) — the React hook / Vue composable
  • DatastripesScatterChart / <datastripes-scatter-chart> — a dedicated canvas scatter plot

How it works ​

Points are flagged using the Mahalanobis distance from the bivariate mean: the distance from a point to the center of the cloud, scaled by the covariance of x and y. Unlike a plain Euclidean distance, this accounts for the shape and orientation of the cloud, so a point that's far along the natural correlation between x and y is treated as normal, while a point that breaks that correlation is flagged even if it isn't far from the center in raw distance.

ts
interface ScatterHyperparameters {
  threshold?: number; // Mahalanobis distance threshold, default 3
}

Usage ​

Headless (any framework) ​

ts
import { executeScatterAnomalyDetection } from '@datastripes/anomaly';

const result = await executeScatterAnomalyDetection({
  data: rows, // e.g. [{ cpu: 42, memory: 61 }, { cpu: 95, memory: 12 }, ...]
  columnMapping: { xKey: 'cpu', yKey: 'memory' } // omit to auto-discover
});

console.log(result.metrics.anomalyCount, result.points);

React ​

tsx
import { useScatterAnomalyDetection, DatastripesScatterChart } from '@datastripes/anomaly/react';

function CpuMemoryOutliers({ rows }) {
  const { result, isLoading } = useScatterAnomalyDetection({ data: rows });
  if (isLoading || !result) return <p>Scanning…</p>;
  return (
    <DatastripesScatterChart
      points={result.points}
      centerX={result.centerX}
      centerY={result.centerY}
    />
  );
}

Vue ​

vue
<script setup>
import { useScatterAnomalyDetection } from '@datastripes/anomaly/vue';
import { DatastripesScatterChart } from '@datastripes/anomaly/vue';

const { result } = useScatterAnomalyDetection(() => ({ data: rows }));
</script>

<template>
  <DatastripesScatterChart
    v-if="result"
    :points="result.points"
    :center-x="result.centerX"
    :center-y="result.centerY"
  />
</template>

Angular ​

html
<datastripes-scatter-chart
  [points]="result.points"
  [centerX]="result.centerX"
  [centerY]="result.centerY"
/>

Vanilla / Web Components ​

html
<datastripes-scatter-chart id="chart"></datastripes-scatter-chart>
<script type="module">
  import { executeScatterAnomalyDetection } from '@datastripes/anomaly';
  const result = await executeScatterAnomalyDetection({ data: rows });
  const chart = document.getElementById('chart');
  chart.points = result.points;
  chart.centerX = result.centerX;
  chart.centerY = result.centerY;
</script>

See the full live demo at Scatter detection example and the type definitions in the Types Reference.