Skip to content

Quick Start

Get up and running with LOESS in minutes.

Smooth a noisy sine wave — the kind of signal where LOESS shines. Each example recovers the underlying trend from 100 points of Gaussian noise.

const { Loess } = require('fastloess');
// 100-point noisy sine wave
const n = 100;
const x = Float64Array.from({ length: n }, (_, i) => i * 2 * Math.PI / (n - 1));
const y = Float64Array.from(x, (xi, i) => Math.sin(xi) + (((i * 7 + 3) % 17) / 17 - 0.5) * 0.6);
const model = new Loess({ fraction: 0.3, iterations: 3 });
const result = model.fit(x, y);
console.log(`First smoothed: ${result.y[0].toFixed(4)} (true: ${Math.sin(x[0]).toFixed(4)})`);
First smoothed: 0.0281 (true: 0.0000)

const { Loess } = require('fastloess');
const n = 100;
const x = Float64Array.from({ length: n }, (_, i) => i * 2 * Math.PI / (n - 1));
const y = Float64Array.from(x, (xi, i) => Math.sin(xi) + (((i*7+3)%17)/17-0.5)*0.6);
const model = new Loess({
fraction: 0.5,
iterations: 3,
outputs: ["diagnostics"],
intervals: { confidence : 0.95, prediction : 0.95 }
});
const result = model.fit(x, y);
console.log("Smoothed (first 5):", [...result.y.slice(0, 5)].map(v => v.toFixed(4)));
console.log("CI lower (first 5):", [...result.confidence_lower.slice(0, 5)].map(v => v.toFixed(4)));
console.log("CI upper (first 5):", [...result.confidence_upper.slice(0, 5)].map(v => v.toFixed(4)));
console.log("R2:", result.diagnostics.r_squared.toFixed(4));
Smoothed (first 5): [ '0.1118', '0.1389', '0.1702', '0.2064', '0.2445' ]
CI lower (first 5): [ '-0.0075', '0.0204', '0.0524', '0.0894', '0.1284' ]
CI upper (first 5): [ '0.2311', '0.2575', '0.2879', '0.3233', '0.3605' ]
R2: 0.8860

LOESS can robustly handle outliers through iterative reweighting:

const { Loess } = require('fastloess');
const xOut = new Float64Array([1, 2, 3, 4, 5, 6]);
const yWithOutlier = new Float64Array([2.0, 4.0, 6.0, 50.0, 10.0, 12.0]);
const model = new Loess({
fraction: 0.7,
iterations: 5,
robustness_method: "bisquare",
outputs: ["weights"]
});
const result = model.fit(xOut, yWithOutlier);
// Outliers will have low robustness weights
result.robustness_weights.forEach((w, i) => {
if (w < 0.5) {
console.log(`Point ${i} is likely an outlier (weight: ${w.toFixed(3)})`);
}
});
Point 3 is likely an outlier (weight: 0.000)

For datasets too large to fit in memory, stream them in fixed-size chunks with overlap.

const { StreamingLoess } = require('fastloess');
const n = 5000;
const x = Float64Array.from({ length: n }, (_, i) => i * 10 * Math.PI / (n - 1));
const y = Float64Array.from(x, (xi, i) =>
Math.sin(xi / Math.PI) * Math.exp(-xi / 30) +
(((i * 7 + 3) % 17) / 17 - 0.5) * 0.3
);
const model = new StreamingLoess(
{ fraction: 0.2 },
{ chunk_size: 1000, overlap: 100, merge_strategy: 'weighted_average' }
);
const chunk_size = 1000;
for (let start = 0; start <= 4000; start += chunk_size) {
const end = Math.min(start + chunk_size, n);
model.process_chunk(x.slice(start, end), y.slice(start, end));
}
const result = model.finalize();
console.log(`Smoothed ${result.y.length} points in streaming mode`);
Smoothed 100 points in streaming mode

TopicLink
How LOESS worksConcepts
All parameters explainedAPI Reference
Batch vs Streaming vs OnlineExecution Modes
Polynomial degree choicesDegree
Multivariate smoothingDimensions
Edge handlingBoundary
Outlier handling in depthRobustness
Full API per languageAPI Reference