lowess ====== LOWESS (Locally Weighted Scatterplot Smoothing) for robust nonparametric regression. .. currentmodule:: smooth .. autofunction:: smooth.lowess Overview -------- LOWESS is a nonparametric regression method that combines polynomial regression with local weighting. It is particularly useful for: - **Smoothing noisy data** while preserving local patterns - **Robust estimation** that is resistant to outliers - **Exploratory data analysis** to reveal underlying trends The implementation exactly matches R's ``stats::lowess`` function, ensuring reproducibility across R and Python workflows. Example Usage ------------- Basic smoothing: .. code-block:: python from smooth import lowess import numpy as np # Generate noisy data x = np.linspace(0, 2*np.pi, 50) y = np.sin(x) + np.random.randn(50) * 0.3 # Apply LOWESS smoothing result = lowess(x, y) # Access smoothed values x_smooth = result['x'] # Sorted x values y_smooth = result['y'] # Smoothed y values Adjusting smoothness: .. code-block:: python # More smoothing (larger span) result_smooth = lowess(x, y, f=0.8) # Less smoothing (smaller span) result_rough = lowess(x, y, f=0.2) Handling outliers: .. code-block:: python # Add outliers y_outliers = y.copy() y_outliers[10] = 5 # Outlier # LOWESS is robust to outliers due to iterative reweighting result = lowess(x, y_outliers, iter=3) # Default iterations # More iterations for heavily contaminated data result_robust = lowess(x, y_outliers, iter=5) Using 2D input (R-style): .. code-block:: python # Combine x and y into 2D array xy = np.column_stack([x, y]) # Call with single argument result = lowess(xy) Parameters ---------- **x** : array-like X values. Can be 1D array or 2D array with x in first column. *(required)* **y** : array-like, optional Y values. Optional if x is 2D array containing both x and y. Default: ``None`` **f** : float, optional Smoother span (fraction of points). Larger values = smoother. Default: ``2/3`` **iter** : int, optional Number of robustifying iterations. More = more robust. Default: ``3`` **delta** : float, optional Distance threshold for interpolation. Points within delta are treated as the same point. Default: ``0.01 * range(x)`` Returns ------- The function returns a dictionary with two keys: **x** : ndarray Sorted x values. **y** : ndarray Smoothed y values corresponding to sorted x. Algorithm --------- LOWESS uses Cleveland's (1979) algorithm: 1. **Local Fitting**: At each point, fit a weighted linear regression using nearby points. Weights decrease with distance using a tricube function. 2. **Robustness Iterations**: Recompute weights based on residuals to downweight outliers. Repeat ``iter`` times. 3. **Interpolation**: For efficiency, only compute fits at a subset of points and interpolate between them (controlled by ``delta``). The tricube weight function is: .. math:: w(u) = (1 - |u|^3)^3 \quad \text{for } |u| < 1 References ---------- Cleveland, W.S. (1979) "Robust Locally Weighted Regression and Smoothing Scatterplots". *Journal of the American Statistical Association* 74(368): 829-836. See Also -------- - :doc:`msdecompose` - Uses LOWESS internally for trend extraction - R's ``stats::lowess`` - Equivalent R function