fastlowess-wasm 0.99.8 β 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +172 -336
- package/fastlowess_wasm.d.ts +121 -97
- package/fastlowess_wasm.js +542 -317
- package/fastlowess_wasm_bg.wasm +0 -0
- package/package.json +17 -1
package/README.md
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
<!-- markdownlint-disable MD024 MD033 -->
|
|
2
2
|
# LOWESS Project
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
<p align="center">
|
|
5
|
+
<a href="https://crates.io/crates/lowess"><img src="https://img.shields.io/badge/lowess-000000?logo=rust&logoColor=white" alt="lowess"></a>
|
|
6
|
+
<a href="https://crates.io/crates/fastLowess"><img src="https://img.shields.io/badge/fastLowess-000000?logo=rust&logoColor=white" alt="fastLowess"></a>
|
|
7
|
+
<a href="https://pypi.org/project/fastlowess/"><img src="https://img.shields.io/badge/PyPI-3775A9?logo=pypi&logoColor=white" alt="PyPI"></a>
|
|
8
|
+
<a href="https://thisisamirv.r-universe.dev/rfastlowess"><img src="https://img.shields.io/badge/R--universe-276DC3?logo=r&logoColor=white" alt="R-universe"></a>
|
|
9
|
+
<a href="https://www.npmjs.com/package/fastlowess"><img src="https://img.shields.io/badge/npm-CB3837?logo=npm&logoColor=white" alt="npm"></a>
|
|
10
|
+
<a href="https://juliahub.com/ui/Packages/General/fastlowess_jll"><img src="https://img.shields.io/badge/Julia-9558B2?logo=julia&logoColor=white" alt="Julia"></a>
|
|
11
|
+
<a href="https://www.npmjs.com/package/fastlowess-wasm"><img src="https://img.shields.io/badge/WASM-654FF0?logo=webassembly&logoColor=white" alt="WASM"></a>
|
|
12
|
+
<a href="https://github.com/thisisamirv/lowess-project/releases/latest"><img src="https://img.shields.io/badge/C++-00599C?logo=cplusplus&logoColor=white" alt="C++"></a>
|
|
13
|
+
<br>
|
|
14
|
+
<a href="https://anaconda.org/conda-forge/fastlowess"><img src="https://img.shields.io/badge/fastlowess_(Python)-44A833?logo=anaconda&logoColor=white" alt="fastlowess (Python)"></a>
|
|
15
|
+
<a href="https://anaconda.org/conda-forge/libfastlowess"><img src="https://img.shields.io/badge/libfastlowess_(C++)-44A833?logo=anaconda&logoColor=white" alt="libfastlowess (C++)"></a>
|
|
16
|
+
<a href="https://anaconda.org/conda-forge/r-rfastlowess"><img src="https://img.shields.io/badge/rfastlowess_(R)-44A833?logo=anaconda&logoColor=white" alt="rfastlowess (R)"></a>
|
|
17
|
+
</p>
|
|
10
18
|
|
|
11
19
|
<p align="center">
|
|
12
20
|
<img src="https://raw.githubusercontent.com/thisisamirv/lowess-project/main/dev/logo.png" alt="One LOWESS to Rule Them All" width="400">
|
|
@@ -20,14 +28,30 @@ The fastest, most robust, and most feature-complete language-agnostic LOWESS (Lo
|
|
|
20
28
|
>
|
|
21
29
|
> The `lowess-project` contains a complete ecosystem for LOWESS smoothing:
|
|
22
30
|
>
|
|
23
|
-
> - **[`lowess`](https://
|
|
24
|
-
> - **[`fastLowess`](https://
|
|
25
|
-
> - **[`R bindings`](https://
|
|
26
|
-
> - **[`Python bindings`](https://
|
|
27
|
-
> - **[`Julia bindings`](https://
|
|
28
|
-
> - **[`JavaScript bindings`](https://
|
|
29
|
-
> - **[`WebAssembly bindings`](https://
|
|
30
|
-
> - **[`C++ bindings`](https://github.com/thisisamirv/lowess-project/
|
|
31
|
+
> - **[`lowess`](https://crates.io/crates/lowess)** - Core single-threaded Rust implementation with `no_std` support
|
|
32
|
+
> - **[`fastLowess`](https://crates.io/crates/fastLowess)** - Parallel CPU and GPU-accelerated Rust wrapper with ndarray integration
|
|
33
|
+
> - **[`R bindings`](https://thisisamirv.r-universe.dev/rfastlowess)** - extendr-based R binding
|
|
34
|
+
> - **[`Python bindings`](https://pypi.org/project/fastlowess/)** - PyO3-based Python binding
|
|
35
|
+
> - **[`Julia bindings`](https://juliahub.com/ui/Packages/General/fastlowess_jll)** - Native Julia binding with C FFI
|
|
36
|
+
> - **[`JavaScript bindings`](https://www.npmjs.com/package/fastlowess)** - Node.js binding
|
|
37
|
+
> - **[`WebAssembly bindings`](https://www.npmjs.com/package/fastlowess-wasm)** - WASM binding
|
|
38
|
+
> - **[`C++ bindings`](https://github.com/thisisamirv/lowess-project/releases/latest)** - Native C++ binding with CMake integration
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
> [!NOTE]
|
|
45
|
+
>
|
|
46
|
+
> Currently available for R, Python, Rust, Julia, Node.js, WebAssembly, and C++. See [INSTALLATION.md](https://github.com/thisisamirv/lowess-project/blob/main/INSTALLATION.md) for detailed installation instructions.
|
|
47
|
+
|
|
48
|
+
## Documentation
|
|
49
|
+
|
|
50
|
+
> [!NOTE]
|
|
51
|
+
>
|
|
52
|
+
> ### π [View the full documentation](https://lowess.readthedocs.io/)
|
|
53
|
+
|
|
54
|
+
---
|
|
31
55
|
|
|
32
56
|
## LOESS vs. LOWESS
|
|
33
57
|
|
|
@@ -43,38 +67,13 @@ The fastest, most robust, and most feature-complete language-agnostic LOWESS (Lo
|
|
|
43
67
|
|
|
44
68
|
---
|
|
45
69
|
|
|
46
|
-
## Documentation
|
|
47
|
-
|
|
48
|
-
> [!NOTE]
|
|
49
|
-
>
|
|
50
|
-
> ### π [View the full documentation](https://lowess.readthedocs.io/)
|
|
51
|
-
|
|
52
70
|
## Why this package?
|
|
53
71
|
|
|
54
72
|
### Speed
|
|
55
73
|
|
|
56
|
-
The `lowess` project
|
|
57
|
-
|
|
58
|
-
Speedup relative to Python's `statsmodels.lowess` (higher is better):
|
|
59
|
-
|
|
60
|
-
| Category | statsmodels | R (stats) | Serial | Parallel | GPU |
|
|
61
|
-
|---------------------------------|-------------|-----------|--------|----------|---------|
|
|
62
|
-
| **Clustered** | 163ms | 83Γ | 203Γ | **433Γ** | 32Γ |
|
|
63
|
-
| **Constant Y** | 134ms | 92Γ | 212Γ | **410Γ** | 18Γ |
|
|
64
|
-
| **Delta** (largeβnone) | 105ms | 2Γ | 4Γ | 6Γ | **16Γ** |
|
|
65
|
-
| **Extreme Outliers** | 489ms | 106Γ | 201Γ | **388Γ** | 29Γ |
|
|
66
|
-
| **Financial** (500β10K) | 106ms | 105Γ | 252Γ | **293Γ** | 12Γ |
|
|
67
|
-
| **Fraction** (0.05β0.67) | 221ms | 104Γ | 228Γ | **391Γ** | 22Γ |
|
|
68
|
-
| **Genomic** (1Kβ50K) | 1833ms | 7Γ | 9Γ | 20Γ | **95Γ** |
|
|
69
|
-
| **High Noise** | 435ms | 133Γ | 134Γ | **375Γ** | 32Γ |
|
|
70
|
-
| **Iterations** (0β10) | 204ms | 115Γ | 224Γ | **386Γ** | 18Γ |
|
|
71
|
-
| **Scale** (1Kβ50K) | 1841ms | 264Γ | 487Γ | **581Γ** | 98Γ |
|
|
72
|
-
| **Scientific** (500β10K) | 167ms | 109Γ | 205Γ | **314Γ** | 15Γ |
|
|
73
|
-
| **Scale Large**\* (100Kβ2M) | β | β | 1Γ | **1.4Γ** | 0.3Γ |
|
|
74
|
-
|
|
75
|
-
\*Scale Large benchmarks are relative to Serial (statsmodels cannot handle these sizes)
|
|
74
|
+
The `lowess` project beats the competition in terms of speed, whether in single-threaded or multi-threaded parallel execution. It is on average **200-327x faster** than Python's `statsmodels.lowess` and **2-3x faster** than R's `lowess`.
|
|
76
75
|
|
|
77
|
-
|
|
76
|
+
For more details on the performance comparison, see the [BENCHMARKS](https://github.com/thisisamirv/lowess-project/blob/main/BENCHMARKS.md) file.
|
|
78
77
|
|
|
79
78
|
### Robustness
|
|
80
79
|
|
|
@@ -145,185 +144,12 @@ All implementations are **numerical twins** of R's `lowess`:
|
|
|
145
144
|
| **Consistency** | β
PERFECT | Multiple scenarios pass with strict tolerance |
|
|
146
145
|
| **Robustness** | β
VERIFIED | Robust smoothing matches R exactly |
|
|
147
146
|
|
|
148
|
-
## Installation
|
|
149
|
-
|
|
150
|
-
Currently available for R, Python, Julia, and Rust:
|
|
151
|
-
|
|
152
|
-
**R** (from R-universe, recommended):
|
|
153
|
-
|
|
154
|
-
```r
|
|
155
|
-
install.packages("rfastlowess", repos = "https://thisisamirv.r-universe.dev")
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
**Python** (from PyPI):
|
|
159
|
-
|
|
160
|
-
```bash
|
|
161
|
-
pip install fastlowess
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
Or from conda-forge:
|
|
165
|
-
|
|
166
|
-
```bash
|
|
167
|
-
conda install -c conda-forge fastlowess
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
**Rust** (lowess, no_std compatible):
|
|
171
|
-
|
|
172
|
-
```toml
|
|
173
|
-
[dependencies]
|
|
174
|
-
lowess = "0.99"
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
**Rust** (fastLowess, parallel + GPU):
|
|
178
|
-
|
|
179
|
-
```toml
|
|
180
|
-
[dependencies]
|
|
181
|
-
fastLowess = { version = "0.99", features = ["cpu"] }
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
**Julia** (from Julia General Registry):
|
|
185
|
-
|
|
186
|
-
```julia
|
|
187
|
-
using Pkg
|
|
188
|
-
Pkg.add("fastLowess")
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
**Node.js** (from npm):
|
|
192
|
-
|
|
193
|
-
```bash
|
|
194
|
-
npm install fastlowess
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
**WebAssembly** (from npm):
|
|
198
|
-
|
|
199
|
-
```bash
|
|
200
|
-
npm install fastlowess-wasm
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
Or via CDN:
|
|
204
|
-
|
|
205
|
-
```html
|
|
206
|
-
<script type="module">
|
|
207
|
-
import init, { smooth } from 'https://unpkg.com/fastlowess-wasm@latest';
|
|
208
|
-
await init();
|
|
209
|
-
</script>
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
**C++** (build from source):
|
|
213
|
-
|
|
214
|
-
```bash
|
|
215
|
-
make cpp
|
|
216
|
-
# Links against libfastlowess_cpp.so
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
## Quick Example
|
|
220
|
-
|
|
221
|
-
**R:**
|
|
222
|
-
|
|
223
|
-
```r
|
|
224
|
-
library(rfastlowess)
|
|
225
|
-
|
|
226
|
-
x <- c(1, 2, 3, 4, 5)
|
|
227
|
-
y <- c(2.0, 4.1, 5.9, 8.2, 9.8)
|
|
228
|
-
|
|
229
|
-
result <- fastlowess(x, y, fraction = 0.5, iterations = 3)
|
|
230
|
-
print(result$y)
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
**Python:**
|
|
234
|
-
|
|
235
|
-
```python
|
|
236
|
-
import fastlowess as fl
|
|
237
|
-
import numpy as np
|
|
238
|
-
|
|
239
|
-
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
|
|
240
|
-
y = np.array([2.0, 4.1, 5.9, 8.2, 9.8])
|
|
241
|
-
|
|
242
|
-
result = fl.smooth(x, y, fraction=0.5, iterations=3)
|
|
243
|
-
print(result["y"])
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
**Rust:**
|
|
247
|
-
|
|
248
|
-
```rust
|
|
249
|
-
use lowess::prelude::*;
|
|
250
|
-
|
|
251
|
-
let x = vec![1.0, 2.0, 3.0, 4.0, 5.0];
|
|
252
|
-
let y = vec![2.0, 4.1, 5.9, 8.2, 9.8];
|
|
253
|
-
|
|
254
|
-
let model = Lowess::new()
|
|
255
|
-
.fraction(0.5)
|
|
256
|
-
.iterations(3)
|
|
257
|
-
.adapter(Batch)
|
|
258
|
-
.build()?;
|
|
259
|
-
|
|
260
|
-
let result = model.fit(&x, &y)?;
|
|
261
|
-
println!("{}", result);
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
**Julia:**
|
|
265
|
-
|
|
266
|
-
```julia
|
|
267
|
-
using fastlowess
|
|
268
|
-
|
|
269
|
-
x = [1.0, 2.0, 3.0, 4.0, 5.0]
|
|
270
|
-
y = [2.0, 4.1, 5.9, 8.2, 9.8]
|
|
271
|
-
|
|
272
|
-
result = smooth(x, y, fraction=0.5, iterations=3)
|
|
273
|
-
println(result.y)
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
**Node.js:**
|
|
277
|
-
|
|
278
|
-
```javascript
|
|
279
|
-
const { smooth } = require('fastlowess');
|
|
280
|
-
|
|
281
|
-
const x = [1.0, 2.0, 3.0, 4.0, 5.0];
|
|
282
|
-
const y = [2.0, 4.1, 5.9, 8.2, 9.8];
|
|
283
|
-
|
|
284
|
-
const result = smooth(x, y, { fraction: 0.5, iterations: 3 });
|
|
285
|
-
console.log(result.y);
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
**WebAssembly:**
|
|
289
|
-
|
|
290
|
-
```javascript
|
|
291
|
-
import init, { smooth } from 'fastlowess-wasm';
|
|
292
|
-
|
|
293
|
-
await init();
|
|
294
|
-
|
|
295
|
-
const x = new Float64Array([1.0, 2.0, 3.0, 4.0, 5.0]);
|
|
296
|
-
const y = new Float64Array([2.0, 4.1, 5.9, 8.2, 9.8]);
|
|
297
|
-
|
|
298
|
-
const result = smooth(x, y, { fraction: 0.5, iterations: 3 });
|
|
299
|
-
console.log(result.y);
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
**C++:**
|
|
303
|
-
|
|
304
|
-
```cpp
|
|
305
|
-
#include <fastlowess.hpp>
|
|
306
|
-
|
|
307
|
-
std::vector<double> x = {1.0, 2.0, 3.0, 4.0, 5.0};
|
|
308
|
-
std::vector<double> y = {2.0, 4.1, 5.9, 8.2, 9.8};
|
|
309
|
-
|
|
310
|
-
fastlowess::LowessOptions options;
|
|
311
|
-
options.fraction = 0.5;
|
|
312
|
-
options.iterations = 3;
|
|
313
|
-
|
|
314
|
-
auto result = fastlowess::smooth(x, y, options);
|
|
315
|
-
for (double val : result.y_vector()) std::cout << val << " ";
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
---
|
|
319
|
-
|
|
320
147
|
## API Reference
|
|
321
148
|
|
|
322
149
|
**R:**
|
|
323
150
|
|
|
324
151
|
```r
|
|
325
|
-
|
|
326
|
-
x, y,
|
|
152
|
+
Lowess(
|
|
327
153
|
fraction = 0.5,
|
|
328
154
|
iterations = 3L,
|
|
329
155
|
delta = 0.01,
|
|
@@ -341,14 +167,30 @@ fastlowess(
|
|
|
341
167
|
cv_k = 5L,
|
|
342
168
|
auto_converge = 1e-4,
|
|
343
169
|
parallel = TRUE
|
|
344
|
-
)
|
|
170
|
+
)$fit(x, y)
|
|
171
|
+
|
|
172
|
+
# Result structure:
|
|
173
|
+
result$x,
|
|
174
|
+
result$y,
|
|
175
|
+
result$standard_errors,
|
|
176
|
+
result$confidence_lower,
|
|
177
|
+
result$confidence_upper,
|
|
178
|
+
result$prediction_lower,
|
|
179
|
+
result$prediction_upper,
|
|
180
|
+
result$residuals,
|
|
181
|
+
result$robustness_weights,
|
|
182
|
+
result$diagnostics,
|
|
183
|
+
result$iterations_used,
|
|
184
|
+
result$fraction_used,
|
|
185
|
+
result$cv_scores
|
|
345
186
|
```
|
|
346
187
|
|
|
347
188
|
**Python:**
|
|
348
189
|
|
|
349
190
|
```python
|
|
350
|
-
fastlowess
|
|
351
|
-
|
|
191
|
+
from fastlowess import Lowess
|
|
192
|
+
|
|
193
|
+
model = Lowess(
|
|
352
194
|
fraction=0.5,
|
|
353
195
|
iterations=3,
|
|
354
196
|
delta=0.01,
|
|
@@ -367,16 +209,32 @@ fastlowess.smooth(
|
|
|
367
209
|
auto_converge=1e-4,
|
|
368
210
|
parallel=True
|
|
369
211
|
)
|
|
212
|
+
result = model.fit(x, y)
|
|
213
|
+
|
|
214
|
+
# Result structure:
|
|
215
|
+
result.x,
|
|
216
|
+
result.y,
|
|
217
|
+
result.standard_errors,
|
|
218
|
+
result.confidence_lower,
|
|
219
|
+
result.confidence_upper,
|
|
220
|
+
result.prediction_lower,
|
|
221
|
+
result.prediction_upper,
|
|
222
|
+
result.residuals,
|
|
223
|
+
result.robustness_weights,
|
|
224
|
+
result.diagnostics,
|
|
225
|
+
result.iterations_used,
|
|
226
|
+
result.fraction_used,
|
|
227
|
+
result.cv_scores
|
|
370
228
|
```
|
|
371
229
|
|
|
372
230
|
**Rust:**
|
|
373
231
|
|
|
374
232
|
```rust
|
|
375
233
|
Lowess::new()
|
|
376
|
-
.fraction(0.5)
|
|
377
|
-
.iterations(3)
|
|
378
|
-
.delta(0.01)
|
|
379
|
-
.weight_function(Tricube)
|
|
234
|
+
.fraction(0.5)
|
|
235
|
+
.iterations(3)
|
|
236
|
+
.delta(0.01)
|
|
237
|
+
.weight_function(Tricube)
|
|
380
238
|
.robustness_method(Bisquare)
|
|
381
239
|
.zero_weight_fallback(UseLocalMean)
|
|
382
240
|
.boundary_policy(Extend)
|
|
@@ -387,17 +245,35 @@ Lowess::new()
|
|
|
387
245
|
.return_robustness_weights()
|
|
388
246
|
.cross_validate(KFold(5, &[0.3, 0.5, 0.7]).seed(123))
|
|
389
247
|
.auto_converge(1e-4)
|
|
390
|
-
.adapter(Batch)
|
|
248
|
+
.adapter(Batch)
|
|
391
249
|
.parallel(true) // fastLowess only
|
|
392
250
|
.backend(CPU) // fastLowess only: CPU or GPU
|
|
393
251
|
.build()?;
|
|
252
|
+
|
|
253
|
+
let result = model.fit(x, y);
|
|
254
|
+
|
|
255
|
+
// Result structure:
|
|
256
|
+
pub struct LowessResult<T> {
|
|
257
|
+
pub x: Vec<T>, // Sorted x values
|
|
258
|
+
pub y: Vec<T>, // Smoothed y values
|
|
259
|
+
pub standard_errors: Option<Vec<T>>,
|
|
260
|
+
pub confidence_lower: Option<Vec<T>>,
|
|
261
|
+
pub confidence_upper: Option<Vec<T>>,
|
|
262
|
+
pub prediction_lower: Option<Vec<T>>,
|
|
263
|
+
pub prediction_upper: Option<Vec<T>>,
|
|
264
|
+
pub residuals: Option<Vec<T>>,
|
|
265
|
+
pub robustness_weights: Option<Vec<T>>,
|
|
266
|
+
pub diagnostics: Option<Diagnostics<T>>,
|
|
267
|
+
pub iterations_used: Option<usize>,
|
|
268
|
+
pub fraction_used: T,
|
|
269
|
+
pub cv_scores: Option<Vec<T>>,
|
|
270
|
+
}
|
|
394
271
|
```
|
|
395
272
|
|
|
396
273
|
**Julia:**
|
|
397
274
|
|
|
398
275
|
```julia
|
|
399
|
-
|
|
400
|
-
x, y,
|
|
276
|
+
Lowess(;
|
|
401
277
|
fraction=0.5,
|
|
402
278
|
iterations=3,
|
|
403
279
|
delta=NaN, # NaN for auto
|
|
@@ -405,23 +281,38 @@ smooth(
|
|
|
405
281
|
robustness_method="bisquare",
|
|
406
282
|
zero_weight_fallback="use_local_mean",
|
|
407
283
|
boundary_policy="extend",
|
|
408
|
-
confidence_intervals=
|
|
409
|
-
prediction_intervals=
|
|
284
|
+
confidence_intervals=NaN,
|
|
285
|
+
prediction_intervals=NaN,
|
|
410
286
|
return_diagnostics=true,
|
|
411
287
|
return_residuals=true,
|
|
412
288
|
return_robustness_weights=true,
|
|
413
|
-
cv_fractions=[0.3, 0.5
|
|
289
|
+
cv_fractions=Float64[], # e.g. [0.3, 0.5]
|
|
414
290
|
cv_method="kfold",
|
|
415
291
|
cv_k=5,
|
|
416
|
-
auto_converge=
|
|
292
|
+
auto_converge=NaN,
|
|
417
293
|
parallel=true
|
|
418
294
|
)
|
|
295
|
+
|
|
296
|
+
# Result structure:
|
|
297
|
+
result.x,
|
|
298
|
+
result.y,
|
|
299
|
+
result.standard_errors,
|
|
300
|
+
result.confidence_lower,
|
|
301
|
+
result.confidence_upper,
|
|
302
|
+
result.prediction_lower,
|
|
303
|
+
result.prediction_upper,
|
|
304
|
+
result.residuals,
|
|
305
|
+
result.robustness_weights,
|
|
306
|
+
result.diagnostics,
|
|
307
|
+
result.iterations_used,
|
|
308
|
+
result.fraction_used,
|
|
309
|
+
result.cv_scores
|
|
419
310
|
```
|
|
420
311
|
|
|
421
312
|
**Node.js:**
|
|
422
313
|
|
|
423
314
|
```javascript
|
|
424
|
-
|
|
315
|
+
new Lowess({
|
|
425
316
|
fraction: 0.5,
|
|
426
317
|
iterations: 3,
|
|
427
318
|
delta: 0.01,
|
|
@@ -439,7 +330,22 @@ smooth(x, y, {
|
|
|
439
330
|
cvK: 5,
|
|
440
331
|
autoConverge: 1e-4,
|
|
441
332
|
parallel: true
|
|
442
|
-
})
|
|
333
|
+
}).fit(x, y)
|
|
334
|
+
|
|
335
|
+
// Result structure:
|
|
336
|
+
result.x,
|
|
337
|
+
result.y,
|
|
338
|
+
result.standardErrors,
|
|
339
|
+
result.confidenceLower,
|
|
340
|
+
result.confidenceUpper,
|
|
341
|
+
result.predictionLower,
|
|
342
|
+
result.predictionUpper,
|
|
343
|
+
result.residuals,
|
|
344
|
+
result.robustnessWeights,
|
|
345
|
+
result.diagnostics,
|
|
346
|
+
result.iterationsUsed,
|
|
347
|
+
result.fractionUsed,
|
|
348
|
+
result.cvScores
|
|
443
349
|
```
|
|
444
350
|
|
|
445
351
|
**WebAssembly:**
|
|
@@ -461,8 +367,24 @@ smooth(x, y, {
|
|
|
461
367
|
cvFractions: [0.3, 0.5, 0.7],
|
|
462
368
|
cvMethod: "kfold",
|
|
463
369
|
cvK: 5,
|
|
464
|
-
autoConverge: 1e-4
|
|
370
|
+
autoConverge: 1e-4,
|
|
371
|
+
parallel: true
|
|
465
372
|
})
|
|
373
|
+
|
|
374
|
+
// Result structure:
|
|
375
|
+
result.x,
|
|
376
|
+
result.y,
|
|
377
|
+
result.standardErrors,
|
|
378
|
+
result.confidenceLower,
|
|
379
|
+
result.confidenceUpper,
|
|
380
|
+
result.predictionLower,
|
|
381
|
+
result.predictionUpper,
|
|
382
|
+
result.residuals,
|
|
383
|
+
result.robustnessWeights,
|
|
384
|
+
result.diagnostics,
|
|
385
|
+
result.iterationsUsed,
|
|
386
|
+
result.fractionUsed,
|
|
387
|
+
result.cvScores
|
|
466
388
|
```
|
|
467
389
|
|
|
468
390
|
**C++:**
|
|
@@ -487,99 +409,23 @@ options.cv_k = 5;
|
|
|
487
409
|
options.auto_converge = 1e-4;
|
|
488
410
|
options.parallel = true;
|
|
489
411
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
result
|
|
499
|
-
result
|
|
500
|
-
result
|
|
501
|
-
result
|
|
502
|
-
result
|
|
503
|
-
result
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
```python
|
|
509
|
-
result.x, result.y, result.standard_errors
|
|
510
|
-
result.confidence_lower, result.confidence_upper
|
|
511
|
-
result.prediction_lower, result.prediction_upper
|
|
512
|
-
result.residuals, result.robustness_weights
|
|
513
|
-
result.diagnostics, result.iterations_used
|
|
514
|
-
result.fraction_used, result.cv_scores
|
|
515
|
-
```
|
|
516
|
-
|
|
517
|
-
**Rust:**
|
|
518
|
-
|
|
519
|
-
```rust
|
|
520
|
-
pub struct LowessResult<T> {
|
|
521
|
-
pub x: Vec<T>, // Sorted x values
|
|
522
|
-
pub y: Vec<T>, // Smoothed y values
|
|
523
|
-
pub standard_errors: Option<Vec<T>>,
|
|
524
|
-
pub confidence_lower: Option<Vec<T>>,
|
|
525
|
-
pub confidence_upper: Option<Vec<T>>,
|
|
526
|
-
pub prediction_lower: Option<Vec<T>>,
|
|
527
|
-
pub prediction_upper: Option<Vec<T>>,
|
|
528
|
-
pub residuals: Option<Vec<T>>,
|
|
529
|
-
pub robustness_weights: Option<Vec<T>>,
|
|
530
|
-
pub diagnostics: Option<Diagnostics<T>>,
|
|
531
|
-
pub iterations_used: Option<usize>,
|
|
532
|
-
pub fraction_used: T,
|
|
533
|
-
pub cv_scores: Option<Vec<T>>,
|
|
534
|
-
}
|
|
535
|
-
```
|
|
536
|
-
|
|
537
|
-
**Julia:**
|
|
538
|
-
|
|
539
|
-
```julia
|
|
540
|
-
result.x, result.y, result.standard_errors
|
|
541
|
-
result.confidence_lower, result.confidence_upper
|
|
542
|
-
result.prediction_lower, result.prediction_upper
|
|
543
|
-
result.residuals, result.robustness_weights
|
|
544
|
-
result.diagnostics, result.iterations_used
|
|
545
|
-
result.fraction_used
|
|
546
|
-
```
|
|
547
|
-
|
|
548
|
-
**Node.js:**
|
|
549
|
-
|
|
550
|
-
```javascript
|
|
551
|
-
result.x, result.y, result.standardErrors
|
|
552
|
-
result.confidenceLower, result.confidenceUpper
|
|
553
|
-
result.predictionLower, result.predictionUpper
|
|
554
|
-
result.residuals, result.robustnessWeights
|
|
555
|
-
result.diagnostics, result.iterationsUsed
|
|
556
|
-
result.fractionUsed, result.cvScores
|
|
557
|
-
```
|
|
558
|
-
|
|
559
|
-
**WebAssembly:**
|
|
560
|
-
|
|
561
|
-
```javascript
|
|
562
|
-
result.x, result.y, result.standardErrors
|
|
563
|
-
result.confidenceLower, result.confidenceUpper
|
|
564
|
-
result.predictionLower, result.predictionUpper
|
|
565
|
-
result.residuals, result.robustnessWeights
|
|
566
|
-
result.diagnostics, result.iterationsUsed
|
|
567
|
-
result.fractionUsed, result.cvScores
|
|
568
|
-
```
|
|
569
|
-
|
|
570
|
-
**C++:**
|
|
571
|
-
|
|
572
|
-
```cpp
|
|
573
|
-
result.y_vector() // std::vector<double>
|
|
574
|
-
result.confidence_lower() // std::vector<double>
|
|
575
|
-
result.confidence_upper() // std::vector<double>
|
|
576
|
-
result.prediction_lower() // std::vector<double>
|
|
577
|
-
result.prediction_upper() // std::vector<double>
|
|
578
|
-
result.residuals() // std::vector<double>
|
|
579
|
-
result.robustness_weights() // std::vector<double>
|
|
580
|
-
result.diagnostics() // Diagnostics struct
|
|
581
|
-
result.iterations_used() // size_t
|
|
582
|
-
result.fraction_used() // double
|
|
412
|
+
fastlowess::Lowess model(options);
|
|
413
|
+
auto result = model.fit(x, y);
|
|
414
|
+
|
|
415
|
+
// Result structure:
|
|
416
|
+
result.x_vector(),
|
|
417
|
+
result.y_vector(),
|
|
418
|
+
result.standard_errors(),
|
|
419
|
+
result.confidence_lower(),
|
|
420
|
+
result.confidence_upper(),
|
|
421
|
+
result.prediction_lower(),
|
|
422
|
+
result.prediction_upper(),
|
|
423
|
+
result.residuals(),
|
|
424
|
+
result.robustness_weights(),
|
|
425
|
+
result.diagnostics(),
|
|
426
|
+
result.iterations_used(),
|
|
427
|
+
result.fraction_used(),
|
|
428
|
+
result.cv_scores()
|
|
583
429
|
```
|
|
584
430
|
|
|
585
431
|
---
|
|
@@ -590,17 +436,7 @@ Contributions are welcome! Please see the [CONTRIBUTING.md](https://github.com/t
|
|
|
590
436
|
|
|
591
437
|
## License
|
|
592
438
|
|
|
593
|
-
Licensed under
|
|
594
|
-
|
|
595
|
-
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or <https://www.apache.org/licenses/LICENSE-2.0>)
|
|
596
|
-
- MIT license ([LICENSE-MIT](LICENSE-MIT) or <https://opensource.org/licenses/MIT>)
|
|
597
|
-
|
|
598
|
-
at your option.
|
|
599
|
-
|
|
600
|
-
## References
|
|
601
|
-
|
|
602
|
-
- Cleveland, W.S. (1979). "Robust Locally Weighted Regression and Smoothing Scatterplots". *JASA*.
|
|
603
|
-
- Cleveland, W.S. (1981). "LOWESS: A Program for Smoothing Scatterplots". *The American Statistician*.
|
|
439
|
+
Licensed under [MIT](https://github.com/thisisamirv/lowess-project/blob/main/LICENSE-MIT) or [Apache-2.0](https://github.com/thisisamirv/lowess-project/blob/main/LICENSE-APACHE).
|
|
604
440
|
|
|
605
441
|
## Citation
|
|
606
442
|
|