Skip to content

Custom Weights

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

Standard LOESS 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 jj in a local fit centred at xix_i is:

wij=custom_weights[j]×K ⁣(dijhi)×rjw_{ij} = \text{custom\_weights}[j] \times K\!\left(\frac{d_{ij}}{h_i}\right) \times r_j

where KK is the distance kernel, hih_i is the local bandwidth, and rjr_j is the robustness weight from the current iteration.

custom_weights supplies one finite non-negative prior weight per observation. Batch accepts a vector with fit; Streaming accepts process_chunk_weighted; Online accepts add_point_weighted or add_point_vector_weighted. Streaming preserves weights through overlap buffers, and Online evicts each weight with its observation. Existing unweighted calls use weight 1.0.


SituationRecommended weight
Point known to be erroneous0.0 — fully excluded
Unreliable sensor / low precision0.1 – 0.5
Standard observation1.0 (default)
Carefully calibrated measurement> 1.0
Measurement uncertainty σi\sigma_i1/σi21 / \sigma_i^2

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

Custom WeightsRobustness Iterations
When knownBefore fittingComputed from residuals
Knowledge requiredPrior knowledge of qualityNone — data-driven
EffectFixed throughout fitAdapts each iteration
Use caseKnown bad sensors, calibrationUnknown 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 { Loess } = require('fastloess-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(y.length).fill(1);
weights[4] = 0; // Exclude 5th point
const model = new Loess({});
const result = model.fit(x, y, weights);
console.log("y[0]:", result.y[0].toFixed(4));
y[0]: 0.1578

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

const { Loess } = require('fastloess-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 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 Loess({ fraction: 0.5 });
const result = model.fit(x, y, weights);
console.log("y[0]:", result.y[0].toFixed(4));
y[0]: 0.3134

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

const { Loess } = require('fastloess-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 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 Loess({ fraction: 0.5 });
const result = model.fit(x, y, weights);
console.log("y[0]:", result.y[0].toFixed(4));
y[0]: 0.3284

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

const { Loess } = require('fastloess-wasm');
const x = Float64Array.from({ length: 20 }, (_, i) => i);
const y = Float64Array.from({ length: 20 }, (_, i) => i * 1.5);
y[3] = -50.0; // known bad
y[12] = 80.0; // unknown outlier
const weights = new Float64Array(20).fill(1.0);
weights[3] = 0.0;
const model = new Loess({ fraction: 0.4, iterations: 3 });
const result = model.fit(x, y, weights);
console.log("y[0]:", result.y[0].toFixed(4));
y[0]: 0.8674

RuleEffect
Length must equal nError at fit time if mismatched
All values must be ≥ 0Negative weights are rejected
All-zero weight vectorError: no points remain for any local fit
Uniform weights (1.0 everywhere)Identical result to omitting weights