LOWESS Project¶
The fastest, most robust, and most feature-complete language-agnostic LOWESS (Locally Weighted Scatterplot Smoothing) implementation for Rust, Python, R, Julia, JavaScript, C++, and WebAssembly.
What is LOWESS?¶
LOWESS is a nonparametric regression method that fits smooth curves through scatter plots. At each point, it fits a weighted polynomial using nearby data, with weights decreasing smoothly with distance. This creates flexible, data-adaptive curves without assuming a global functional form.
Key advantages:
- No parametric assumptions — Adapts to local data structure
- Robust to outliers — With robustness iterations enabled
- Uncertainty quantification — Confidence and prediction intervals
- Handles irregular sampling — Works with missing regions gracefully
Why this package?¶
Speed¶
The lowess project crushes the competition in terms of speed, wether in single-threaded or multi-threaded parallel execution.
Speedup relative to Python's statsmodels.lowess (higher is better):
| Category | statsmodels | R (stats) | Serial | Parallel | GPU |
|---|---|---|---|---|---|
| Clustered | 163ms | 83× | 203× | 433× | 32× |
| Constant Y | 134ms | 92× | 212× | 410× | 18× |
| Delta (large–none) |
105ms | 2× | 4× | 6× | 16× |
| Extreme Outliers | 489ms | 106× | 201× | 388× | 29× |
| Financial (500–10K) |
106ms | 105× | 252× | 293× | 12× |
| Fraction (0.05–0.67) |
221ms | 104× | 228× | 391× | 22× |
| Genomic (1K–50K) |
1833ms | 7× | 9× | 20× | 95× |
| High Noise | 435ms | 133× | 134× | 375× | 32× |
| Iterations (0–10) |
204ms | 115× | 224× | 386× | 18× |
| Scale (1K–50K) |
1841ms | 264× | 487× | 581× | 98× |
| Scientific (500–10K) |
167ms | 109× | 205× | 314× | 15× |
| Scale Large* (100K–2M) |
— | — | 1× | 1.4× | 0.3× |
*Scale Large benchmarks are relative to Serial (statsmodels cannot handle these sizes)
The numbers are the average across a range of scenarios for each category (e.g., Delta from none, to small, medium, and large).
Robustness¶
This implementation is more robust than R's lowess and Python's statsmodels due to two key design choices:
MAD-Based Scale Estimation:
For robustness weight calculations, this crate uses Median Absolute Deviation (MAD) for scale estimation:
In contrast, statsmodels and R's lowess uses the median of absolute residuals (MAR):
- MAD is a breakdown-point-optimal estimator—it remains valid even when up to 50% of data are outliers.
- The median-centering step removes asymmetric bias from residual distributions.
- MAD provides consistent outlier detection regardless of whether residuals are centered around zero.
Boundary Padding:
This crate applies a range of different boundary policies at dataset edges:
- Extend: Repeats edge values to maintain local neighborhood size.
- Reflect: Mirrors data symmetrically around boundaries.
- Zero: Pads with zeros (useful for signal processing).
- NoBoundary: Original Cleveland behavior
statsmodels and R's lowess do not apply boundary padding, which can lead to:
- Biased estimates near boundaries due to asymmetric local neighborhoods.
- Increased variance at the edges of the smoothed curve.
Features¶
A variety of features, supporting a range of use cases:
| Feature | This package | statsmodels | R (stats) |
|---|---|---|---|
| Kernel | 7 options | only Tricube | only Tricube |
| Robustness Weighting | 3 options | only Huber | only Huber |
| Scale Estimation | 2 options | only MAR | only MAR |
| Boundary Padding | 4 options | no padding | no padding |
| Zero Weight Fallback | 3 options | no | no |
| Auto Convergence | yes | no | no |
| Online Mode | yes | no | no |
| Streaming Mode | yes | no | no |
| Confidence Intervals | yes | no | no |
| Prediction Intervals | yes | no | no |
| Cross-Validation | 2 options | no | no |
| Parallel Execution | yes | no | no |
| GPU Acceleration | yes* | no | no |
no-std Support |
yes | no | no |
* GPU acceleration is currently in beta and may not be available on all platforms.
Installation¶
Currently available for R, Python, Rust, Julia, Node.js, and WebAssembly.
From R-universe (recommended, no Rust toolchain required):
Or from conda-forge:
Install from PyPI:
Or from conda-forge:
Add the crate to your Cargo.toml:
Install from npm:
Or via CDN:
See the Installation Guide for more options and details.
Quick Example¶
#include <fastlowess.hpp>
#include <iostream>
#include <vector>
int main() {
std::vector<double> x = {1.0, 2.0, 3.0, 4.0, 5.0};
std::vector<double> y = {2.0, 4.1, 5.9, 8.2, 9.8};
fastlowess::LowessOptions options;
options.fraction = 0.5;
options.iterations = 3;
fastlowess::Lowess model(options);
auto result = model.fit(x, y);
for (const auto& val : result.yVector()) {
std::cout << val << " ";
}
std::cout << std::endl;
return 0;
}
Getting Started¶
- Installation — Set up the library for your language
- Quick Start — Basic usage examples
- Concepts — Understand how LOWESS works
-
Rust
Pure Rust crates with zero-copy ndarray support, parallel execution, and GPU acceleration.
-
Python
Native Python bindings via PyO3 with NumPy integration and pip installation.
-
R
R package with Bioconductor-style documentation and seamless integration.
-
Julia
Native Julia package with C FFI, supporting parallel execution and JLL dependencies.
-
Node.js
Native Node.js bindings with high-performance C++ core and support for asynchronous streaming.
-
WebAssembly
Optimized WebAssembly build for browsers and Node.js with zero-overhead data transfer.
-
C++
Native C++ bindings with RAII memory management and STL container support.
License¶
Dual-licensed under MIT or Apache-2.0.