Quick Start

Basic Smoothing

Smooth a noisy sine wave — the kind of signal where LOESS shines. fraction = 0.3 and iterations = 3 are good starting values for most signals.

library(rfastloess)

# 100-point noisy sine wave
set.seed(42)
x <- seq(0, 2 * pi, length.out = 100)
y <- sin(x) + rnorm(100, sd = 0.3)

model <- Loess(fraction = 0.3, iterations = 3)
result <- fit(model, x, y)

cat(sprintf("First smoothed value: %.4f (true: %.4f)\n",
            result$y[1], sin(x[1])))
#> First smoothed value: 0.4263 (true: 0.0000)

With Confidence Intervals

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

model <- Loess(
    fraction = 0.5,
    iterations = 3,
    outputs = "diagnostics",
    intervals = intervals_opts(confidence = 0.95, prediction = 0.95)
)
result <- fit(model, x, y)

cat("Smoothed (first 5):", head(result$y, 5), "\n")
#> Smoothed (first 5): 0.4758389 0.4846388 0.4944609 0.5054102 0.5169758
cat("CI Lower (first 5):", head(result$confidence_lower, 5), "\n")
#> CI Lower (first 5): 0.3394052 0.346882 0.3553893 0.3651472 0.3757715
cat("CI Upper (first 5):", head(result$confidence_upper, 5), "\n")
#> CI Upper (first 5): 0.6122726 0.6223956 0.6335326 0.6456731 0.65818
cat("R2:", result$diagnostics$r_squared, "\n")
#> R2: 0.78173

Handling Outliers

LOESS can robustly handle outliers through iterative reweighting:

library(rfastloess)

x_out <- 1:6
y_with_outlier <- c(2.0, 4.0, 6.0, 50.0, 10.0, 12.0)

model <- Loess(
    fraction = 0.7,
    iterations = 5,
    robustness_method = "bisquare",
    outputs = "weights"
)
result <- fit(model, x_out, y_with_outlier)

# Check which points were downweighted
for (i in seq_along(result$robustness_weights)) {
    if (result$robustness_weights[i] < 0.5) {
        cat(sprintf("Point %d is likely an outlier (weight: %.3f)\n",
                    i, result$robustness_weights[i]))
    }
}
#> Point 4 is likely an outlier (weight: 0.000)

Streaming Mode

For datasets too large to fit in memory, stream them in fixed-size chunks with overlap.

library(rfastloess)
set.seed(42)
x <- seq(0, 10 * pi, length.out = 5000)
y <- sin(x / pi) * exp(-x / 30) + rnorm(5000, sd = 0.15)

model <- StreamingLoess(
    fraction = 0.2,
    chunk_size = 1000,
    overlap = 100,
    merge_strategy = "weighted_average"
)

chunk_size <- 1000
for (start in seq(1, 4001, by = chunk_size)) {
    end <- min(start + chunk_size - 1, length(x))
    process_chunk(model, x[start:end], y[start:end])
}
result <- finalize(model)
cat("Smoothed", length(result$y), "points in streaming mode\n")
#> Smoothed 100 points in streaming mode

Online Mode

For real-time / point-by-point processing.

library(rfastloess)
set.seed(42)
times <- 1:100
temperatures <- 20 + 5 * sin(times / 10) + rnorm(100)

model <- OnlineLoess(
    fraction = 0.3,
    window_capacity = 25,
    min_points = 5,
    update_mode = "incremental"
)

for (i in seq_along(times)) {
    result <- add_point(model, times[i], temperatures[i])
    if (!is.null(result))
        cat(sprintf("Time %d: %.2f\n", times[i], result$y))
    if (i >= 10) break  # print only the first few outputs
}
#> Time 5: 22.80
#> Time 6: 22.72
#> Time 7: 24.73
#> Time 8: 23.49
#> Time 9: 25.94
#> Time 10: 24.14

Plotting Results

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

model <- Loess(fraction = 0.5, intervals = intervals_opts(confidence = 0.95))
result <- fit(model, x, y)

plot(x, y, pch = 16, col = "gray", main = "LOESS Smoothing")
lines(result$x, result$y, col = "blue", lwd = 2)
lines(result$x, result$confidence_lower, col = "blue", lty = 2)
lines(result$x, result$confidence_upper, col = "blue", lty = 2)
legend("topright", c("Data", "Smoothed", "95% CI"),
        pch = c(16, NA, NA), lty = c(NA, 1, 2),
        col = c("gray", "blue", "blue"))


Next Steps

Topic Link
How LOESS works vignette("concepts", package = "rfastloess")
Comparing with stats::loess() vignette("alternative-software", package = "rfastloess")
All parameters explained ?Loess
Batch vs Streaming vs Online vignette("adapter-choice")
Polynomial degree choices vignette("degree", package = "rfastloess")
Multivariate smoothing vignette("dimensions", package = "rfastloess")
Edge handling vignette("boundary", package = "rfastloess")
Outlier handling in depth vignette("robustness", package = "rfastloess")
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