Skip to content

Custom Weights

Per-observation weights that encode data quality directly into the LOWESS fit.

Standard LOWESS assigns equal prior trust to all observations. Custom weights let you override this assumption point by point — before any distance or robustness weighting is applied.

The effective weight of observation $j$ in a local fit centred at $x_i$ is:

$$w_{ij} = \text{custom_weights}[j] \times K!\left(\frac{d_{ij}}{h_i}\right) \times r_j$$

where $K$ is the distance kernel, $h_i$ is the local bandwidth, and $r_j$ is the robustness weight from the current iteration.

Streaming and Online adapters.

Situation Recommended weight
Point known to be erroneous 0.0 — fully excluded
Unreliable sensor / low precision 0.1 – 0.5
Standard observation 1.0 (default)
Carefully calibrated measurement > 1.0
Measurement uncertainty $\sigma_i$ $1 / \sigma_i^2$

Both mechanisms handle unreliable data, but they serve different purposes:

Custom Weights Robustness Iterations
When known Before fitting Computed from residuals
Knowledge required Prior knowledge of quality None — data-driven
Effect Fixed throughout fit Adapts each iteration
Use case Known bad sensors, calibration Unknown outlier contamination

They compose: you can use both simultaneously. Custom weights suppress a priori bad points; robustness iterations then handle any residual outliers that remain.


Set the weight to 0 at the bad point — it is excluded from every local fit that would otherwise include it.

const { Lowess } = require('fastlowess-wasm');
const x = Float64Array.from({length: 10}, (_, i) => i);
const y = Float64Array.from(x, v => v * 2);
y[5] = 100.0; // spike
const weights = new Float64Array(10).fill(1.0);
weights[5] = 0.0; // exclude the spike
const model = new Lowess({fraction: 0.5, iterations: 0});
const result = model.fit(x, y, weights);
console.log("y[0]:", result.y[0].toFixed(4));
y[0]: 0.5726

Assign high weights to measurements you trust most — calibration standards, reference instruments, or low-noise observations.

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 calibrationIndices = [5, 20, 40, 60, 80];
const weights = new Float64Array(x.length).fill(1.0);
for (const i of calibrationIndices) weights[i] = 10.0;
const model = new Lowess({fraction: 0.5});
const result = model.fit(x, y, weights);
console.log("y[0]:", result.y[0].toFixed(4));
y[0]: 0.0865

If each observation has a known standard deviation $\sigma_i$, set $w_i = 1 / \sigma_i^2$ to give the fit information-theoretically optimal weighting.

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 sigma = Float64Array.from({ length: n }, (_, i) => 0.1 + (i % 4) * 0.1);
const weights = Float64Array.from(sigma, s => 1.0 / (s * s));
const model = new Lowess({fraction: 0.5});
const result = model.fit(x, y, weights);
console.log("y[0]:", result.y[0].toFixed(4));
y[0]: 0.0090

Custom weights and robustness iterations compose naturally: use custom weights for known bad points and robustness for unknown contamination.

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 weights = new Float64Array(x.length).fill(1.0);
weights[3] = 0.0;
const model = new Lowess({fraction: 0.4, iterations: 3});
const result = model.fit(x, y, weights);
console.log("y[0]:", result.y[0].toFixed(4));
y[0]: 0.0809

Rule Effect
Length must equal n Error at fit time if mismatched
All values must be ≥ 0 Negative weights are rejected
All-zero weight vector Error: no points remain for any local fit
Uniform weights (1.0 everywhere) Identical result to omitting weights
that centre point falls back to the behaviour specified by
`zero_weight_fallback` (default: `"use_local_mean"`).