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 \(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.
custom_weights supplies one finite non-negative prior
weight per observation. Batch accepts weights in fit;
Streaming accepts process_chunk(..., custom_weights=...);
Online accepts add_point(..., weight=...). Streaming
preserves weights through overlap buffers, and Online evicts each weight
with its observation. Existing unweighted calls use weight
1.0.
| 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 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.
library(rfastloess)
x <- 0:9
y <- x * 2.0
y[6] <- 100.0 # spike at index 5 (0-based)
weights <- rep(1.0, 10)
weights[6] <- 0.0 # exclude the spike
model <- Loess(fraction = 0.5, iterations = 0L)
result <- fit(model, x, y, custom_weights = weights)
cat("Smoothed y[0]:", result$y[1], "\n")
#> Smoothed y[0]: 0.572621Assign high weights to measurements you trust most — calibration standards, reference instruments, or low-noise observations.
library(rfastloess)
set.seed(42)
x <- seq(0, 2 * pi, length.out = 100)
y <- sin(x) + rnorm(100, sd = 0.3)
calibration_indices <- c(6, 21, 41, 61, 81)
weights <- rep(1.0, length(x))
weights[calibration_indices] <- 10.0 # trust calibration 10x more
model <- Loess(fraction = 0.5)
result <- fit(model, x, y, custom_weights = weights)
cat("Smoothed y[0]:", result$y[1], "\n")
#> Smoothed y[0]: 0.4228696If each observation has a known standard deviation \(\sigma_i\), set \(w_i = 1 / \sigma_i^2\) to give the fit information-theoretically optimal weighting.
library(rfastloess)
set.seed(42)
x <- seq(0, 2 * pi, length.out = 100)
y <- sin(x) + rnorm(100, sd = 0.3)
sigma <- runif(100, 0.1, 0.5)
weights <- 1 / sigma^2
model <- Loess(fraction = 0.5)
result <- fit(model, x, y, custom_weights = weights)
cat("Smoothed y[0]:", result$y[1], "\n")
#> Smoothed y[0]: 0.4414661Custom weights and robustness iterations compose naturally: use custom weights for known bad points and robustness for unknown contamination.
library(rfastloess)
x <- 0:19
y <- x * 1.5
y[4] <- -50.0 # known bad
y[13] <- 80.0 # unknown outlier
weights <- rep(1.0, 20)
weights[4] <- 0.0
model <- Loess(fraction = 0.4, iterations = 3)
result <- fit(model, x, y, custom_weights = weights)
cat("Smoothed y[0]:", result$y[1], "\n")
#> Smoothed y[0]: 0.8673742| 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 |
Zero-weight windows: If a local neighbourhood contains only zero-weight points, the fit at that centre point falls back to the behaviour specified by
zero_weight_fallback(default:"use_local_mean").
vignette("robustness", package = "rfastloess") —
adaptive outlier downweighting via IRLS?Loess — full parameter referencesessionInfo()
#> R version 4.6.1 (2026-06-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 26.04.1 LTS
#>
#> Matrix products: default
#> BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
#> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.32.so; LAPACK version 3.12.0
#>
#> locale:
#> [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
#> [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
#> [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
#> [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
#> [9] LC_ADDRESS=C LC_TELEPHONE=C
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: Etc/UTC
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] rfastloess_3.0.0 rmarkdown_2.32
#>
#> loaded via a namespace (and not attached):
#> [1] digest_0.6.39 R6_2.6.1 fastmap_1.2.0 xfun_0.61
#> [5] maketools_1.3.2 cachem_1.1.0 knitr_1.52 htmltools_0.5.9
#> [9] buildtools_1.0.0 lifecycle_1.0.5 cli_3.6.6 sass_0.4.10
#> [13] jquerylib_0.1.4 compiler_4.6.1 sys_3.4.3 tools_4.6.1
#> [17] evaluate_1.0.5 bslib_0.12.0 yaml_2.3.12 otel_0.2.0
#> [21] jsonlite_2.0.0 rlang_1.3.0