Skip to content

Quick Start

Get up and running with LOWESS in minutes.

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

const { Lowess } = require('fastlowess-wasm');
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 Lowess({ fraction: 0.3, iterations: 3 });
const result = model.fit(x, y);
console.log(`First smoothed: ${result.y[0].toFixed(4)}`);
First smoothed: 0.0278

const { Lowess } = require('fastlowess-wasm');
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 Lowess({
fraction: 0.5,
iterations: 3,
confidence_intervals: 0.95,
prediction_intervals: 0.95,
return_diagnostics: true
});
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("R²:", result.diagnostics.r_squared.toFixed(4));
Smoothed (first 5): [ '0.1181', '0.1502', '0.1833', '0.2172', '0.2518' ]
CI lower (first 5): [ '0.0551', '0.0762', '0.1205', '0.1405', '0.1770' ]
CI upper (first 5): [ '0.1812', '0.2243', '0.2461', '0.2938', '0.3266' ]
R²: 0.9022

LOWESS can robustly handle outliers through iterative reweighting:

const { Lowess } = require('fastlowess-wasm');
// Data with an outlier at position 3
const x = new Float64Array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
const yWithOutlier = new Float64Array([2.0, 4.0, 6.0, 50.0, 10.0, 12.0]);
const model = new Lowess({
fraction: 0.7,
iterations: 5,
robustness_method: "bisquare",
return_robustness_weights: true
});
const result = model.fit(x, 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 { StreamingLowess } = require('fastlowess-wasm');
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 StreamingLowess(
{ 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`);
Smoothed 100 points

TopicLink
How LOWESS worksConcepts
All parameters explainedAPI Reference
Batch vs Streaming vs OnlineExecution Modes
Edge handlingBoundary
Outlier handling in depthRobustness
Full API per languageAPI Reference