char_lowess: Locally-weighted linear regression matching MATLAB...

View source: R/char_lowess.R

char_lowessR Documentation

Locally-weighted linear regression matching MATLAB charLowess.m / smooth()

Description

Pure-R implementation of the shifted-window lowess algorithm from MATLAB's charLowess.m v2.0, which itself replicates MATLAB's smooth(y, k, 'lowess') from the Curve Fitting Toolbox. Replaces the previous wrapper around lowess, which used a shrinking window at record boundaries and different tricubic weight normalisation, causing systematic differences of ~1e-3 in charBkg.

Usage

char_lowess(y, x = NULL, span = 0.1, iter = 0L)

Arguments

y

Numeric vector of values to smooth (NaN-free; bridge NaNs before calling and restore afterward, matching the MATLAB workflow).

x

Numeric vector of x-positions (same length as y). If NULL, seq_along(y) is used (index coordinates).

span

Smoothing span.

  • span >= 1: number of data points.

  • span < 1: fraction of data length.

Converted to integer k = max(3, round(span * n)) or max(3, round(span)), matching charLowess.m lines 63-68.

iter

Number of bisquare robustness passes after the initial fit.

  • iter = 0: plain lowess (1 total WLS pass, no robustness).

  • iter = 4: robust lowess, matching MATLAB's 'rlowess' which uses nIter = 5 total iterations (1 initial + 4 updates).

Details

## Algorithm For each point i, a window of exactly k points is selected: the window is centred on i at interior points and SHIFTED (not shrunk) at record boundaries, maintaining k neighbours throughout. Each neighbour j receives a tricubic weight:

w_j = \left(1 - \left(\frac{|i-j|}{d_{\max}}\right)^3\right)^3

where d_{\max} is the distance to the furthest point in the window (not the half-window radius). A weighted least-squares line is fitted and evaluated at i. This matches charLowess.m lines 109-147 exactly.

For iter > 0 ('rlowess'), bisquare robustness weights are computed from the residuals after each WLS pass and multiplied into the tricubic weights for the next pass (matching charLowess.m lines 151-157).

## Why not stats::lowess()? stats::lowess() trims (shrinks) the window at boundaries and normalises tricubic weights by the half-window radius hw. The two differences compound to ~1e-3 absolute error in charBkg for the CO dataset (500 yr / 15 yr = 33-point window, 17-point boundary zone).

Value

Numeric vector of smoothed values, same length as y.

See Also

[char_smooth()], [char_thresh_local()]


CharAnalysis documentation built on May 3, 2026, 5:06 p.m.