Quick Start¶
Get up and running with LOWESS in minutes.
Basic Smoothing¶
use lowess::prelude::*;
fn main() -> Result<(), LowessError> {
// Sample data
let x = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
let y = vec![2.1, 3.8, 6.2, 7.9, 10.3, 11.8, 14.1, 15.7];
// Build and fit the model
let model = Lowess::new()
.fraction(0.5) // Use 50% of data for each fit
.iterations(3) // 3 robustness iterations
.adapter(Batch)
.build()?;
let result = model.fit(&x, &y)?;
println!("{}", result);
Ok(())
}
const fastlowess = require('fastlowess');
// Sample data
const x = new Float64Array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]);
const y = new Float64Array([2.1, 3.8, 6.2, 7.9, 10.3, 11.8, 14.1, 15.7]);
// Smooth the data
const result = fastlowess.smooth(x, y, { fraction: 0.5, iterations: 3 });
console.log("Smoothed values:", result.y);
import * as fastlowess from 'fastlowess-wasm';
// Sample data
const x = new Float64Array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]);
const y = new Float64Array([2.1, 3.8, 6.2, 7.9, 10.3, 11.8, 14.1, 15.7]);
// Smooth the data
const result = fastlowess.smooth(x, y, { fraction: 0.5, iterations: 3 });
console.log("Smoothed values:", result.y);
#include <fastlowess.hpp>
#include <iostream>
#include <vector>
int main() {
// Sample data
std::vector<double> x = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
std::vector<double> y = {2.1, 3.8, 6.2, 7.9, 10.3, 11.8, 14.1, 15.7};
// Smooth the data
fastlowess::LowessOptions options;
options.fraction = 0.5;
options.iterations = 3;
fastlowess::Lowess model(options);
auto result = model.fit(x, y);
// Print smoothed values
const auto& y_smooth = result.yVector();
std::cout << "Smoothed values: [";
for (double val : y_smooth) std::cout << val << ", ";
std::cout << "]" << std::endl;
return 0;
}
With Confidence Intervals¶
result = fl.smooth(
x, y,
fraction=0.5,
iterations=3,
confidence_intervals=0.95,
prediction_intervals=0.95,
return_diagnostics=True
)
print("Smoothed:", result["y"])
print("CI Lower:", result["confidence_lower"])
print("CI Upper:", result["confidence_upper"])
print("R²:", result["diagnostics"]["r_squared"])
use lowess::prelude::*;
let model = Lowess::new()
.fraction(0.5)
.iterations(3)
.confidence_intervals(0.95) // 95% CI
.prediction_intervals(0.95) // 95% PI
.return_diagnostics()
.adapter(Batch)
.build()?;
let result = model.fit(&x, &y)?;
// Access intervals
if let Some(ci_lower) = &result.confidence_lower {
println!("CI Lower: {:?}", ci_lower);
}
result = smooth(
x, y,
fraction=0.5,
iterations=3,
confidence_intervals=0.95,
prediction_intervals=0.95,
return_diagnostics=true
)
println("Smoothed: ", result.y)
println("CI Lower: ", result.confidence_lower)
println("CI Upper: ", result.confidence_upper)
println("R²: ", result.diagnostics.r_squared)
const result = fastlowess.smooth(x, y, {
fraction: 0.5,
iterations: 3,
confidenceIntervals: 0.95,
predictionIntervals: 0.95,
returnDiagnostics: true
});
console.log("Smoothed:", result.y);
console.log("CI Lower:", result.confidenceLower);
console.log("CI Upper:", result.confidenceUpper);
console.log("R²:", result.diagnostics.rSquared);
import * as fastlowess from 'fastlowess-wasm';
// Sample data
const x = new Float64Array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]);
const y = new Float64Array([2.1, 3.8, 6.2, 7.9, 10.3, 11.8, 14.1, 15.7]);
// Smooth the data
const result = fastlowess.smooth(x, y, { fraction: 0.5, iterations: 3 });
console.log("Smoothed values:", result.y);
fastlowess::LowessOptions options;
options.fraction = 0.5;
options.iterations = 3;
options.confidence_intervals = 0.95;
options.prediction_intervals = 0.95;
options.return_diagnostics = true;
fastlowess::Lowess model(options);
auto result = model.fit(x, y);
// Access standard C++ vectors
auto lower = result.confidenceLower();
auto upper = result.confidenceUpper();
double r2 = result.diagnostics().rSquared();
Handling Outliers¶
LOWESS can robustly handle outliers through iterative reweighting:
y_with_outlier <- c(2, 4, 6, 50, 10, 12)
model <- Lowess(
fraction = 0.5,
iterations = 5,
robustness_method = "bisquare",
return_robustness_weights = TRUE
)
result <- model$fit(x, y_with_outlier)
# Check downweighted points
weights <- result$robustness_weights
for (i in seq_along(weights)) {
if (weights[i] < 0.5) {
cat(sprintf("Point %d is likely an outlier (weight: %.3f)\n", i, weights[i]))
}
}
y_with_outlier = np.array([2.0, 4.0, 6.0, 50.0, 10.0, 12.0])
result = fl.smooth(
x, y_with_outlier,
fraction=0.5,
iterations=5,
robustness_method="bisquare",
return_robustness_weights=True
)
# Check which points were downweighted
for i, w in enumerate(result["robustness_weights"]):
if w < 0.5:
print(f"Point {i} is likely an outlier (weight: {w:.3f})")
// Data with an outlier at position 3
let y_with_outlier = vec![2.0, 4.0, 6.0, 50.0, 10.0, 12.0]; // 50.0 is outlier
let model = Lowess::new()
.fraction(0.5)
.iterations(5) // More iterations for outliers
.robustness_method(Bisquare) // Default, smooth downweighting
.return_robustness_weights() // See which points were downweighted
.adapter(Batch)
.build()?;
let result = model.fit(&x, &y_with_outlier)?;
// Outliers will have low robustness weights
if let Some(weights) = &result.robustness_weights {
for (i, w) in weights.iter().enumerate() {
if *w < 0.5 {
println!("Point {} is likely an outlier (weight: {:.3})", i, w);
}
}
}
y_with_outlier = [2.0, 4.0, 6.0, 50.0, 10.0, 12.0]
result = smooth(
x, y_with_outlier,
fraction=0.5,
iterations=5,
robustness_method="bisquare",
return_robustness_weights=true
)
# Check which points were downweighted
for (i, w) in enumerate(result.robustness_weights)
if w < 0.5
println("Point $i is likely an outlier (weight: $(round(w, digits=3)))")
end
end
const fl = require('fastlowess');
const yWithOutlier = new Float64Array([2.0, 4.0, 6.0, 50.0, 10.0, 12.0]);
const result = fl.smooth(x, yWithOutlier, {
fraction: 0.5,
iterations: 5,
robustnessMethod: "bisquare",
returnRobustnessWeights: true
});
// Outliers will have low robustness weights
result.robustnessWeights.forEach((w, i) => {
if (w < 0.5) {
console.log(`Point ${i} is likely an outlier (weight: ${w.toFixed(3)})`);
}
});
import { smooth } from 'fastlowess-wasm';
// Data with an outlier at position 3
const yWithOutlier = new Float64Array([2.0, 4.0, 6.0, 50.0, 10.0, 12.0]);
const result = smooth(x, yWithOutlier, {
fraction: 0.5,
iterations: 5,
robustnessMethod: "bisquare",
returnRobustnessWeights: true
});
// Outliers will have low robustness weights
result.robustnessWeights.forEach((w, i) => {
if (w < 0.5) {
console.log(`Point ${i} is likely an outlier (weight: ${w.toFixed(3)})`);
}
});
// Data with an outlier
std::vector<double> y_outlier = {2.0, 4.0, 6.0, 50.0, 10.0, 12.0};
fastlowess::LowessOptions options;
options.fraction = 0.5;
options.iterations = 5;
options.robustness_method = "bisquare";
options.return_robustness_weights = true;
fastlowess::Lowess model(options);
auto result = model.fit(x, y_outlier);
// Check weights
auto weights = result.robustnessWeights();
for (size_t i = 0; i < weights.size(); ++i) {
if (weights[i] < 0.5) {
std::cout << "Point " << i << " is outlier (weight: " << weights[i] << ")\n";
}
}
Next Steps¶
- Concepts — Understand how LOWESS works
- Parameters — All configuration options
- Execution Modes — Batch, Streaming, Online
- API — Full references