Time Series Analysis
LOESS for trend extraction and temporal smoothing.
Overview
Section titled “Overview”Time series data often contains noise, seasonality, and trends. LOESS provides flexible trend extraction without parametric assumptions.
Basic Trend Extraction
Section titled “Basic Trend Extraction”fraction = 0.1 sizes the neighbourhood as 10% of the data at each evaluation point — narrow enough to follow a slowly varying trend without smearing periodic variation. Three robustness iterations down-weight noise spikes so they cannot bias the fitted curve; this is especially important when the signal-to-noise ratio is low or when occasional outliers are expected.
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 model = new Loess({ fraction: 0.1, iterations: 3});const result = model.fit(x, y);console.log("y[0]:", result.y[0].toFixed(4));y[0]: -0.0964Detrending
Section titled “Detrending”Remove trend to analyze residual patterns.
Setting outputs: ["residuals"] stores observed − smoothed alongside the smooth. A slightly wider fraction = 0.3 produces a smoother baseline trend, so short-duration oscillations end up in the residuals rather than being absorbed into the trend component. The residual series is then ready for spectral analysis, seasonality detection, or change-point methods.
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 model = new Loess({ fraction: 0.3, iterations: 3, outputs: ["residuals"]});const result = model.fit(x, y);console.log("y[0]:", result.y[0].toFixed(4), "residual[0]:", result.residuals[0].toFixed(4));y[0]: 0.0281 residual[0]: -0.2222Forecasting with Prediction Intervals
Section titled “Forecasting with Prediction Intervals”Prediction intervals widen the uncertainty band to include both the uncertainty in the fitted curve (confidence interval) and the expected scatter of new observations around it. fraction = 0.2 offers a balance between local detail and stable interval width — too small a fraction produces jagged interval edges; too large a fraction underestimates local variance near turning points.
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 model = new Loess({ fraction: 0.2, iterations: 3, intervals: { prediction : 0.95 }});const result = model.fit(x, y);console.log("Prediction lower[0]:", result.prediction_lower[0].toFixed(4));Prediction lower[0]: -0.5069Handling Missing Data
Section titled “Handling Missing Data”LOESS naturally handles irregular time sampling:
const { Loess } = require('fastloess-wasm');
const n = 100;const tIrregular = Float64Array.from({ length: n }, (_, i) => i * 1.0 + (i * 31 % 10) * 0.1).sort((a, b) => a - b);const yIrregular = Float64Array.from(tIrregular, t => 10 + 0.3 * t + 2.0 * Math.sin(t * 0.1));const model = new Loess({ fraction: 0.2 });const result = model.fit(tIrregular, yIrregular);console.log("y[0]:", result.y[0].toFixed(4));y[0]: 10.8052Multi-Scale Analysis
Section titled “Multi-Scale Analysis”Use different fractions to extract features at different scales:
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 trends = [0.05, 0.2, 0.5].map(f => { const model = new Loess({ fraction: f }); const result = model.fit(x, y); return result.y;});console.log("Trend y[0] values:", trends.map(t => t[0].toFixed(4)));Trend y[0] values: [ '-0.1050', '-0.0262', '0.1118' ]Gene Expression Time Course
Section titled “Gene Expression Time Course”Biological application:
const { Loess } = require('fastloess-wasm');
const n = 24;const hours = Float64Array.from({ length: n }, (_, i) => i);const expression = Float64Array.from(hours, h => 5 + 3 * Math.sin(h * Math.PI / 12) + (h % 3) * 0.2);const model = new Loess({ fraction: 0.3, iterations: 3, outputs: ["diagnostics"] });const result = model.fit(hours, expression);
console.log("R2:", result.diagnostics?.r_squared);R2: 0.9864121418777019Choosing Fraction for Time Series
Section titled “Choosing Fraction for Time Series”| Data Type | Recommended Fraction | Rationale |
|---|---|---|
| Daily data (years) | 0.3–0.5 | Capture annual trends |
| Hourly data (days) | 0.1–0.2 | Capture daily patterns |
| Sensor data (minutes) | 0.05–0.1 | Preserve short-term features |
| Noisy data | Higher | Reduce noise impact |
| Clean data | Lower | Preserve detail |
See Also
Section titled “See Also”- Real-Time Processing — For streaming time series
- Cross-Validation — Optimal fraction selection
- Polynomial Degree — Degree 2 for curved trends
- Boundary Handling — Edge bias in trend extraction
- API Reference — Full parameter reference