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 value: ${result.y[0].toFixed(4)} (true: ${Math.sin(x[0]).toFixed(4)})`);
First smoothed value: 0.0273 (true: 0.0000)

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 => Math.sin(xi) + 0.1);
const model = new Lowess({
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.3325', '0.3593', '0.3871', '0.4160', '0.4458' ]
CI lower (first 5): [ '0.2929', '0.3190', '0.3462', '0.3743', '0.4034' ]
CI upper (first 5): [ '0.3722', '0.3995', '0.4280', '0.4576', '0.4881' ]
R2: 0.9668

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",
outputs: ["weights"]
});
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 in streaming mode`);
Smoothed 100 points in streaming mode

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