Scaling Methods

Overview

When iterations > 0, LOESS computes robustness weights by comparing each residual to the current residual scale estimate \(\hat{\sigma}\). The scaling_method parameter controls how \(\hat{\sigma}\) is estimated.

\[w_i = B\!\left(\frac{|r_i|}{6 \cdot \hat{\sigma}}\right)\]

Method Formula Robustness Speed
"mad" Median absolute deviation from median Very robust Moderate
"mar" Median of |residuals| Robust Fast
"mean" Mean of |residuals| Less robust Fastest
Scaling method comparison
Scaling method comparison

MAD — Median Absolute Deviation (Default)

\[\hat{\sigma} = \text{median}(|r_i - \text{median}(r_i)|)\]

First centers residuals at their median, then takes the median of the absolute deviations. Double use of the median makes it highly resistant to extreme outliers.

Use when: Data may contain outliers (default for most applications).

library(rfastloess)
set.seed(42)
x <- seq(0, 2 * pi, length.out = 100)
y <- sin(x) + rnorm(100, sd = 0.3)

model <- Loess(iterations = 3, scaling_method = "mad")
result <- fit(model, x, y)
cat("Smoothed y[0]:", result$y[1], "\n")
#> Smoothed y[0]: 0.4897657

MAR — Median Absolute Residual

\[\hat{\sigma} = \text{median}(|r_i|)\]

Uses the uncentered median — unlike MAD it does not subtract the residual median first. Still robust (median-based), faster (one partial sort instead of two).

Use when: Speed matters and data have minimal systematic bias in residuals.

model <- Loess(iterations = 3, scaling_method = "mar")
result <- fit(model, x, y)
cat("Smoothed y[0]:", result$y[1], "\n")
#> Smoothed y[0]: 0.5096452

Mean — Mean Absolute Residual

\[\hat{\sigma} = \frac{1}{n}\sum_i |r_i|\]

Arithmetic mean of absolute residuals. Non-robust: a single extreme outlier inflates \(\hat{\sigma}\), causing the bisquare weight function to under-downweight other outliers.

Use when: Clean data with no outliers; maximum computation speed required.

model <- Loess(iterations = 3, scaling_method = "mean")
result <- fit(model, x, y)
cat("Smoothed y[0]:", result$y[1], "\n")
#> Smoothed y[0]: 0.512746

Choosing a Scaling Method

Situation Recommended Method
General purpose, possible outliers "mad" (default)
Speed matters; residuals have minimal systematic bias "mar"
Clean data, no outliers "mean"

See vignette("robustness", package = "rfastloess") for a broader discussion of outlier handling.


Comparing Scaling Methods

library(rfastloess)
set.seed(42)
x <- 1:100
y <- sin(x / 10) + rnorm(100, sd = 0.3)
y[c(20, 50, 80)] <- y[c(20, 50, 80)] + 5  # outliers

methods <- c("mad", "mar", "mean")
colors  <- c("blue", "red", "green")

plot(x, y, pch = 16, col = "gray",
    main = "Scaling Method Comparison (with outliers)")

for (i in seq_along(methods)) {
    model  <- Loess(iterations = 3, scaling_method = methods[i])
    result <- fit(model, x, y)
    lines(result$x, result$y, col = colors[i], lwd = 2)
}

legend("topright", methods, col = colors, lwd = 2)

sessionInfo()
#> 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