--- title: "Polynomial Degree" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Polynomial Degree} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>") ``` ## Overview At each target point, LOESS fits a polynomial to the neighbouring data using weighted least squares. The `degree` parameter controls the order of that polynomial. ![Degree comparison](../man/figures/degree_comparison.svg) | Degree | Local Fit | Captures | Risk | | --- | --- | --- | --- | | `0` / `"constant"` | Weighted mean | Level only | Over-smooth; edge bias | | `1` / `"linear"` | Weighted line | Trend (default) | Rarely overfits | | `2` / `"quadratic"` | Parabola | Curvature | Overfits with small `fraction` | | `3` / `"cubic"` | Cubic curve | Inflections | Requires larger `fraction` | | `4` / `"quartic"` | Quartic curve | Fine structure | High variance, rare | Degree can be specified as an integer (`0L`–`4L`) or as a string (`"constant"`, `"linear"`, `"quadratic"`, `"cubic"`, `"quartic"`). --- ## Degree 0 — Local Constant The fit at each point is a weighted mean. Produces very smooth results but ignores local slope, introducing bias wherever the true function changes. **Use when**: Maximum smoothness matters more than accuracy; computationally cheapest. ```{r degree_1} 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, degree = "constant") result <- fit(model, x, y) cat("First 6 smoothed values (constant/Nadaraya-Watson):\n") print(head(result$y)) ``` --- ## Degree 1 — Local Linear (Default) Fits a weighted line through the neighbourhood. Removes first-order bias and handles boundary regions correctly. The right choice for the vast majority of applications. **Use when**: Default; monotone or gently curved data; boundary accuracy matters. ```{r degree_2} model <- Loess(fraction = 0.5, degree = "linear") result <- fit(model, x, y) cat("First 6 smoothed values (linear local regression):\n") print(head(result$y)) ``` --- ## Degree 2 — Local Quadratic Fits a weighted parabola. Captures curvature in the data and reduces bias in regions with strong local curvature, at the cost of higher variance. **Use when**: Data has visible curvature or local extrema; use a larger `fraction` to stabilise the fit. ```{r degree_3} model <- Loess(fraction = 0.5, degree = "quadratic") result <- fit(model, x, y) cat("First 6 smoothed values (quadratic local regression):\n") print(head(result$y)) ``` --- ## Degree 3 — Local Cubic Fits a weighted cubic polynomial. Captures inflections and fine structure but requires a sufficiently large neighbourhood to remain stable. **Use when**: Data has clear S-shaped curves or multiple inflection points; use `fraction` >= 0.5. ```{r degree_4} model <- Loess(fraction = 0.6, degree = "cubic") result <- fit(model, x, y) cat("First 6 smoothed values (cubic local regression):\n") print(head(result$y)) ``` --- ## Degree 4 — Local Quartic Fits a weighted quartic polynomial. Rarely needed in practice; only useful for capturing highly oscillatory local structure. Very prone to overfitting. **Use when**: Fine oscillatory structure is physically meaningful and the dataset is large; always cross-validate. ```{r degree_5} model <- Loess(fraction = 0.7, degree = "quartic") result <- fit(model, x, y) cat("First 6 smoothed values (quartic local regression):\n") print(head(result$y)) ``` --- ## Degree and Boundary Fallback At the dataset boundary, the neighbourhood is one-sided and may not contain enough points to support the requested degree. Setting `boundary_degree_fallback = TRUE` automatically reduces the degree at boundaries to avoid instability. ```{r degree_6} model <- Loess(degree = 2L, boundary_degree_fallback = TRUE) result <- fit(model, x, y) cat("First 6 smoothed values (quadratic, boundary fallback):\n") print(head(result$y)) ``` --- ## Choosing the Right Degree | Situation | Recommended Degree | | --- | --- | | Monotone trend, general purpose | `1` (default) | | Maximum smoothness, speed | `0` | | Clear peaks / valleys / inflections | `2` (with `fraction` >= 0.4) | | S-shaped curves, multiple inflections | `3` (with `fraction` >= 0.5) | | Fine oscillatory structure (rare) | `4` (fraction >= 0.6, CV) | | Boundary accuracy is critical | `1` or `2` (not `0`) | | Very small dataset (n < 50) | `1` | > **Rule of thumb:** Start with `degree = 1` (default). Move to `degree = 2` > only if you see systematic bias in regions of high curvature, and increase > `fraction` at the same time. --- ## Higher Degree Effects ![Higher Degree Comparison](../man/figures/higher_degree_comparison.svg) --- ## Surface Mode The `surface_mode` parameter controls whether LOESS evaluates the local polynomial at every query point or at a sparser grid of vertices with Hermite cubic interpolation in between. | Mode | Behaviour | Speed | Accuracy | | --- | --- | --- | --- | | `"interpolation"` (default) | Anchor + Hermite blend | Faster | Approx | | `"direct"` | Evaluate at every query point | Exact | Full precision | ![Surface Mode Comparison](../man/figures/surface_comparison.svg) ![Degree x Interpolation](../man/figures/degree_interpolation_comparison.svg) See `vignette("dimensions", package = "rfastloess")` for runnable `surface_mode` examples. ```{r session-info} sessionInfo() ```