linreg-core 0.4.0 → 0.5.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 CHANGED
@@ -4,8 +4,10 @@
4
4
  [![Coverage](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/jesse-anderson/linreg-core/main/.github/coverage-badge.json)](https://github.com/jesse-anderson/linreg-core/actions/workflows/ci.yml)
5
5
  [![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue)](LICENSE-MIT)
6
6
  [![Crates.io](https://img.shields.io/crates/v/linreg-core?color=orange)](https://crates.io/crates/linreg-core)
7
+ [![npm](https://img.shields.io/npm/v/linreg-core?color=red)](https://www.npmjs.com/package/linreg-core)
8
+ [![PyPI](https://img.shields.io/pypi/v/linreg-core)](https://pypi.org/project/linreg-core/)
7
9
  [![docs.rs](https://img.shields.io/badge/docs.rs-linreg__core-green)](https://docs.rs/linreg-core)
8
- [![PyPI](https://img.shields.io/badge/pypi-0.4.0-blue)](https://pypi.org/project/linreg-core/)
10
+
9
11
 
10
12
  A lightweight, self-contained linear regression library written in Rust. Compiles to WebAssembly for browser use, Python bindings via PyO3, or runs as a native Rust crate.
11
13
 
@@ -30,17 +32,19 @@ A lightweight, self-contained linear regression library written in Rust. Compile
30
32
  ## Features
31
33
 
32
34
  ### Regression Methods
33
- - **OLS Regression:** Coefficients, standard errors, t-statistics, p-values, confidence intervals
34
- - **Ridge Regression:** L2-regularized regression with optional standardization
35
- - **Lasso Regression:** L1-regularized regression via coordinate descent
36
- - **Elastic Net:** Combined L1 + L2 regularization for variable selection with multicollinearity handling
35
+ - **OLS Regression:** Coefficients, standard errors, t-statistics, p-values, confidence intervals, model selection criteria (AIC, BIC, log-likelihood)
36
+ - **Ridge Regression:** L2-regularized regression with optional standardization, effective degrees of freedom, model selection criteria
37
+ - **Lasso Regression:** L1-regularized regression via coordinate descent with automatic variable selection, convergence tracking, model selection criteria
38
+ - **Elastic Net:** Combined L1 + L2 regularization for variable selection with multicollinearity handling, active set convergence, model selection criteria
39
+ - **LOESS:** Locally estimated scatterplot smoothing for non-parametric curve fitting with configurable span, polynomial degree, and robust fitting
37
40
  - **Lambda Path Generation:** Create regularization paths for cross-validation
38
41
 
39
42
  ### Model Statistics
40
- - R-squared, Adjusted R-squared, F-statistic, F-test p-value
41
- - Residuals, fitted values, leverage (hat matrix diagonal)
42
- - Mean Squared Error (MSE)
43
- - Variance Inflation Factor (VIF) for multicollinearity detection
43
+ - **Fit Metrics:** R-squared, Adjusted R-squared, F-statistic, F-test p-value
44
+ - **Error Metrics:** Mean Squared Error (MSE), Root Mean Squared Error (RMSE), Mean Absolute Error (MAE)
45
+ - **Model Selection:** Log-likelihood, AIC (Akaike Information Criterion), BIC (Bayesian Information Criterion)
46
+ - **Residuals:** Raw residuals, standardized residuals, fitted values, leverage (hat matrix diagonal)
47
+ - **Multicollinearity:** Variance Inflation Factor (VIF) for each predictor
44
48
 
45
49
  ### Diagnostic Tests
46
50
  | Category | Tests |
@@ -49,7 +53,8 @@ A lightweight, self-contained linear regression library written in Rust. Compile
49
53
  | **Heteroscedasticity** | Breusch-Pagan (Koenker variant), White Test (R & Python methods) |
50
54
  | **Normality** | Jarque-Bera, Shapiro-Wilk (n ≤ 5000), Anderson-Darling |
51
55
  | **Autocorrelation** | Durbin-Watson, Breusch-Godfrey (higher-order) |
52
- | **Influence** | Cook's Distance |
56
+ | **Multicollinearity** | Variance Inflation Factor (VIF) |
57
+ | **Influence** | Cook's Distance, DFBETAS, DFFITS |
53
58
 
54
59
  ---
55
60
 
@@ -59,7 +64,7 @@ Add to your `Cargo.toml`:
59
64
 
60
65
  ```toml
61
66
  [dependencies]
62
- linreg-core = { version = "0.4", default-features = false }
67
+ linreg-core = { version = "0.5", default-features = false }
63
68
  ```
64
69
 
65
70
  ### OLS Regression (Rust)
@@ -77,6 +82,9 @@ fn main() -> Result<(), linreg_core::Error> {
77
82
  println!("Coefficients: {:?}", result.coefficients);
78
83
  println!("R-squared: {:.4}", result.r_squared);
79
84
  println!("F-statistic: {:.4}", result.f_statistic);
85
+ println!("Log-likelihood: {:.4}", result.log_likelihood);
86
+ println!("AIC: {:.4}", result.aic);
87
+ println!("BIC: {:.4}", result.bic);
80
88
 
81
89
  Ok(())
82
90
  }
@@ -107,6 +115,10 @@ fn main() -> Result<(), linreg_core::Error> {
107
115
  let result = ridge_fit(&x, &y, &options)?;
108
116
  println!("Intercept: {}", result.intercept);
109
117
  println!("Coefficients: {:?}", result.coefficients);
118
+ println!("R-squared: {:.4}", result.r_squared);
119
+ println!("Effective degrees of freedom: {:.2}", result.effective_df);
120
+ println!("AIC: {:.4}", result.aic);
121
+ println!("BIC: {:.4}", result.bic);
110
122
 
111
123
  Ok(())
112
124
  }
@@ -139,6 +151,8 @@ fn main() -> Result<(), linreg_core::Error> {
139
151
  println!("Intercept: {}", result.intercept);
140
152
  println!("Coefficients: {:?}", result.coefficients);
141
153
  println!("Non-zero coefficients: {}", result.n_nonzero);
154
+ println!("AIC: {:.4}", result.aic);
155
+ println!("BIC: {:.4}", result.bic);
142
156
 
143
157
  Ok(())
144
158
  }
@@ -172,6 +186,8 @@ fn main() -> Result<(), linreg_core::Error> {
172
186
  println!("Intercept: {}", result.intercept);
173
187
  println!("Coefficients: {:?}", result.coefficients);
174
188
  println!("Non-zero coefficients: {}", result.n_nonzero);
189
+ println!("AIC: {:.4}", result.aic);
190
+ println!("BIC: {:.4}", result.bic);
175
191
 
176
192
  Ok(())
177
193
  }
@@ -265,6 +281,9 @@ async function run() {
265
281
  const result = JSON.parse(resultJson);
266
282
  console.log("Coefficients:", result.coefficients);
267
283
  console.log("R-squared:", result.r_squared);
284
+ console.log("Log-likelihood:", result.log_likelihood);
285
+ console.log("AIC:", result.aic);
286
+ console.log("BIC:", result.bic);
268
287
  }
269
288
 
270
289
  run();
@@ -282,6 +301,10 @@ const result = JSON.parse(ridge_regression(
282
301
  ));
283
302
 
284
303
  console.log("Coefficients:", result.coefficients);
304
+ console.log("R-squared:", result.r_squared);
305
+ console.log("Effective degrees of freedom:", result.effective_df);
306
+ console.log("AIC:", result.aic);
307
+ console.log("BIC:", result.bic);
285
308
  ```
286
309
 
287
310
  ### Lasso Regression (WASM)
@@ -299,6 +322,8 @@ const result = JSON.parse(lasso_regression(
299
322
 
300
323
  console.log("Coefficients:", result.coefficients);
301
324
  console.log("Non-zero coefficients:", result.n_nonzero);
325
+ console.log("AIC:", result.aic);
326
+ console.log("BIC:", result.bic);
302
327
  ```
303
328
 
304
329
  ### Elastic Net Regression (WASM)
@@ -317,6 +342,8 @@ const result = JSON.parse(elastic_net_regression(
317
342
 
318
343
  console.log("Coefficients:", result.coefficients);
319
344
  console.log("Non-zero coefficients:", result.n_nonzero);
345
+ console.log("AIC:", result.aic);
346
+ console.log("BIC:", result.bic);
320
347
  ```
321
348
 
322
349
  ### Lambda Path Generation (WASM)
@@ -333,6 +360,22 @@ console.log("Lambda sequence:", path.lambda_path);
333
360
  console.log("Lambda max:", path.lambda_max);
334
361
  ```
335
362
 
363
+ ### LOESS Regression (WASM)
364
+
365
+ ```javascript
366
+ const result = JSON.parse(loess_fit(
367
+ JSON.stringify(y),
368
+ JSON.stringify(x[0]), // Single predictor only (flattened array)
369
+ 0.5, // span (smoothing parameter: 0-1)
370
+ 1, // degree (0=constant, 1=linear, 2=quadratic)
371
+ "direct", // surface method ("direct" or "interpolate")
372
+ 0 // robust iterations (0=disabled, >0=number of iterations)
373
+ ));
374
+
375
+ console.log("Fitted values:", result.fitted_values);
376
+ console.log("Residuals:", result.residuals);
377
+ ```
378
+
336
379
  ### Diagnostic Tests (WASM)
337
380
 
338
381
  ```javascript
@@ -405,6 +448,25 @@ const cd = JSON.parse(cooks_distance_test(
405
448
  JSON.stringify(x)
406
449
  ));
407
450
 
451
+ // DFBETAS (influence on coefficients)
452
+ const dfbetas = JSON.parse(dfbetas_test(
453
+ JSON.stringify(y),
454
+ JSON.stringify(x)
455
+ ));
456
+
457
+ // DFFITS (influence on fitted values)
458
+ const dffits = JSON.parse(dffits_test(
459
+ JSON.stringify(y),
460
+ JSON.stringify(x)
461
+ ));
462
+
463
+ // VIF test (multicollinearity)
464
+ const vif = JSON.parse(vif_test(
465
+ JSON.stringify(y),
466
+ JSON.stringify(x)
467
+ ));
468
+ console.log("VIF values:", vif.vif_values);
469
+
408
470
  // RESET test (functional form)
409
471
  const reset = JSON.parse(reset_test(
410
472
  JSON.stringify(y),
@@ -458,7 +520,7 @@ console.log("Numeric columns:", parsed.numeric_columns);
458
520
  ### Helper Functions (WASM)
459
521
 
460
522
  ```javascript
461
- const version = get_version(); // e.g., "0.4.0"
523
+ const version = get_version(); // e.g., "0.5.0"
462
524
  const msg = test(); // "Rust WASM is working!"
463
525
  ```
464
526
 
@@ -519,7 +581,7 @@ print(result.summary())
519
581
  ```
520
582
 
521
583
  **Result objects** provide:
522
- - Direct attribute access (`result.r_squared`, `result.coefficients`)
584
+ - Direct attribute access (`result.r_squared`, `result.coefficients`, `result.aic`, `result.bic`, `result.log_likelihood`)
523
585
  - `summary()` method for formatted output
524
586
  - `to_dict()` method for JSON serialization
525
587
 
@@ -536,6 +598,9 @@ result = linreg_core.ols_regression(y, x, names)
536
598
  print(f"Coefficients: {result.coefficients}")
537
599
  print(f"R-squared: {result.r_squared}")
538
600
  print(f"F-statistic: {result.f_statistic}")
601
+ print(f"Log-likelihood: {result.log_likelihood}")
602
+ print(f"AIC: {result.aic}")
603
+ print(f"BIC: {result.bic}")
539
604
  ```
540
605
 
541
606
  ### Ridge Regression (Python)
@@ -548,6 +613,9 @@ result = linreg_core.ridge_regression(
548
613
  )
549
614
  print(f"Intercept: {result.intercept}")
550
615
  print(f"Coefficients: {result.coefficients}")
616
+ print(f"Effective degrees of freedom: {result.effective_df:.2f}")
617
+ print(f"AIC: {result.aic}")
618
+ print(f"BIC: {result.bic}")
551
619
  ```
552
620
 
553
621
  ### Lasso Regression (Python)
@@ -564,6 +632,8 @@ print(f"Intercept: {result.intercept}")
564
632
  print(f"Coefficients: {result.coefficients}")
565
633
  print(f"Non-zero: {result.n_nonzero}")
566
634
  print(f"Converged: {result.converged}")
635
+ print(f"AIC: {result.aic}")
636
+ print(f"BIC: {result.bic}")
567
637
  ```
568
638
 
569
639
  ### Elastic Net Regression (Python)
@@ -580,6 +650,8 @@ result = linreg_core.elastic_net_regression(
580
650
  print(f"Intercept: {result.intercept}")
581
651
  print(f"Coefficients: {result.coefficients}")
582
652
  print(f"Non-zero: {result.n_nonzero}")
653
+ print(f"AIC: {result.aic}")
654
+ print(f"BIC: {result.bic}")
583
655
  ```
584
656
 
585
657
  ### Lambda Path Generation (Python)
@@ -631,6 +703,16 @@ ad = linreg_core.anderson_darling_test(y, x)
631
703
  cd = linreg_core.cooks_distance_test(y, x)
632
704
  print(f"Influential points: {cd.influential_4_over_n}")
633
705
 
706
+ # DFBETAS (influence on each coefficient)
707
+ dfbetas = linreg_core.dfbetas_test(y, x)
708
+ print(f"Threshold: {dfbetas.threshold}")
709
+ print(f"Influential obs: {dfbetas.influential_observations}")
710
+
711
+ # DFFITS (influence on fitted values)
712
+ dffits = linreg_core.dffits_test(y, x)
713
+ print(f"Threshold: {dffits.threshold}")
714
+ print(f"Influential obs: {dffits.influential_observations}")
715
+
634
716
  # RESET test (model specification)
635
717
  reset = linreg_core.reset_test(y, x, [2, 3], "fitted")
636
718
 
@@ -698,7 +780,7 @@ print(f"Data rows: {result.n_rows}")
698
780
  For native Rust without WASM overhead:
699
781
 
700
782
  ```toml
701
- linreg-core = { version = "0.4", default-features = false }
783
+ linreg-core = { version = "0.5", default-features = false }
702
784
  ```
703
785
 
704
786
  For Python bindings (built with maturin):
package/linreg_core.d.ts CHANGED
@@ -95,6 +95,50 @@ export function breusch_pagan_test(y_json: string, x_vars_json: string): string;
95
95
  */
96
96
  export function cooks_distance_test(y_json: string, x_vars_json: string): string;
97
97
 
98
+ /**
99
+ * Performs DFBETAS analysis via WASM.
100
+ *
101
+ * DFBETAS measures the influence of each observation on each regression coefficient.
102
+ * For each observation and each coefficient, it computes the standardized change
103
+ * in the coefficient when that observation is omitted.
104
+ *
105
+ * # Arguments
106
+ *
107
+ * * `y_json` - JSON array of response variable values
108
+ * * `x_vars_json` - JSON array of predictor arrays
109
+ *
110
+ * # Returns
111
+ *
112
+ * JSON string containing the DFBETAS matrix, threshold, and influential observations.
113
+ *
114
+ * # Errors
115
+ *
116
+ * Returns a JSON error object if parsing fails or domain check fails.
117
+ */
118
+ export function dfbetas_test(y_json: string, x_vars_json: string): string;
119
+
120
+ /**
121
+ * Performs DFFITS analysis via WASM.
122
+ *
123
+ * DFFITS measures the influence of each observation on its own fitted value.
124
+ * It is the standardized change in the fitted value when that observation
125
+ * is omitted from the model.
126
+ *
127
+ * # Arguments
128
+ *
129
+ * * `y_json` - JSON array of response variable values
130
+ * * `x_vars_json` - JSON array of predictor arrays
131
+ *
132
+ * # Returns
133
+ *
134
+ * JSON string containing the DFFITS vector, threshold, and influential observations.
135
+ *
136
+ * # Errors
137
+ *
138
+ * Returns a JSON error object if parsing fails or domain check fails.
139
+ */
140
+ export function dffits_test(y_json: string, x_vars_json: string): string;
141
+
98
142
  /**
99
143
  * Performs the Durbin-Watson test for autocorrelation via WASM.
100
144
  *
@@ -283,6 +327,65 @@ export function jarque_bera_test(y_json: string, x_vars_json: string): string;
283
327
  */
284
328
  export function lasso_regression(y_json: string, x_vars_json: string, _variable_names: string, lambda: number, standardize: boolean, max_iter: number, tol: number): string;
285
329
 
330
+ /**
331
+ * Performs LOESS regression via WASM.
332
+ *
333
+ * LOESS (Locally Estimated Scatterplot Smoothing) is a non-parametric
334
+ * regression method that fits multiple regressions in local subsets
335
+ * of data to create a smooth curve through the data points.
336
+ *
337
+ * # Arguments
338
+ *
339
+ * * `y_json` - JSON array of response variable values
340
+ * * `x_vars_json` - JSON array of predictor arrays
341
+ * * `span` - Fraction of data used in each local fit (0.0 to 1.0)
342
+ * * `degree` - Degree of local polynomial: 0 (constant), 1 (linear), or 2 (quadratic)
343
+ * * `robust_iterations` - Number of robustness iterations (0 for non-robust fit)
344
+ * * `surface` - Surface computation method: "direct" or "interpolate"
345
+ *
346
+ * # Returns
347
+ *
348
+ * JSON string containing:
349
+ * - `fitted` - Fitted values at each observation point
350
+ * - `span` - Span parameter used
351
+ * - `degree` - Degree of polynomial used
352
+ * - `robust_iterations` - Number of robustness iterations performed
353
+ * - `surface` - Surface computation method used
354
+ *
355
+ * # Errors
356
+ *
357
+ * Returns a JSON error object if parsing fails or domain check fails.
358
+ */
359
+ export function loess_fit(y_json: string, x_vars_json: string, span: number, degree: number, robust_iterations: number, surface: string): string;
360
+
361
+ /**
362
+ * Performs LOESS prediction at new query points via WASM.
363
+ *
364
+ * Predicts LOESS fitted values at arbitrary new points by redoing the
365
+ * local fitting at each query point using the original training data.
366
+ *
367
+ * # Arguments
368
+ *
369
+ * * `new_x_json` - JSON array of new predictor values (p vectors, each of length m)
370
+ * * `original_x_json` - JSON array of original training predictors
371
+ * * `original_y_json` - JSON array of original training response values
372
+ * * `span` - Span parameter (must match the original fit)
373
+ * * `degree` - Degree of polynomial (must match the original fit)
374
+ * * `robust_iterations` - Robustness iterations (must match the original fit)
375
+ * * `surface` - Surface computation method: "direct" or "interpolate"
376
+ *
377
+ * # Returns
378
+ *
379
+ * JSON string containing:
380
+ * - `predictions` - Vector of predicted values at query points
381
+ *
382
+ * # Errors
383
+ *
384
+ * Returns a JSON error object if parsing fails, parameters don't match
385
+ * the original fit, or domain check fails.
386
+ */
387
+ export function loess_predict(new_x_json: string, original_x_json: string, original_y_json: string, span: number, degree: number, robust_iterations: number, surface: string): string;
388
+
286
389
  /**
287
390
  * Generates a lambda path for regularized regression via WASM.
288
391
  *
@@ -652,6 +755,35 @@ export function test_r_accuracy(): string;
652
755
  */
653
756
  export function test_t_critical(df: number, alpha: number): string;
654
757
 
758
+ /**
759
+ * Performs Variance Inflation Factor (VIF) analysis via WASM.
760
+ *
761
+ * VIF measures how much the variance of regression coefficients is inflated
762
+ * due to multicollinearity among predictor variables. High VIF values indicate
763
+ * that a predictor is highly correlated with other predictors.
764
+ *
765
+ * # Arguments
766
+ *
767
+ * * `y_json` - JSON array of response variable values
768
+ * * `x_vars_json` - JSON array of predictor arrays
769
+ *
770
+ * # Returns
771
+ *
772
+ * JSON string containing the maximum VIF, detailed VIF results for each predictor,
773
+ * interpretation, and guidance.
774
+ *
775
+ * # Interpretation
776
+ *
777
+ * - VIF = 1: No correlation with other predictors
778
+ * - VIF > 5: Moderate multicollinearity (concerning)
779
+ * - VIF > 10: High multicollinearity (severe)
780
+ *
781
+ * # Errors
782
+ *
783
+ * Returns a JSON error object if parsing fails or domain check fails.
784
+ */
785
+ export function vif_test(y_json: string, x_vars_json: string): string;
786
+
655
787
  /**
656
788
  * Performs the White test for heteroscedasticity via WASM.
657
789
  *
@@ -683,12 +815,16 @@ export interface InitOutput {
683
815
  readonly breusch_godfrey_test: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number];
684
816
  readonly breusch_pagan_test: (a: number, b: number, c: number, d: number) => [number, number];
685
817
  readonly cooks_distance_test: (a: number, b: number, c: number, d: number) => [number, number];
818
+ readonly dfbetas_test: (a: number, b: number, c: number, d: number) => [number, number];
819
+ readonly dffits_test: (a: number, b: number, c: number, d: number) => [number, number];
686
820
  readonly durbin_watson_test: (a: number, b: number, c: number, d: number) => [number, number];
687
821
  readonly elastic_net_regression: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number) => [number, number];
688
822
  readonly get_version: () => [number, number];
689
823
  readonly harvey_collier_test: (a: number, b: number, c: number, d: number) => [number, number];
690
824
  readonly jarque_bera_test: (a: number, b: number, c: number, d: number) => [number, number];
691
825
  readonly lasso_regression: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => [number, number];
826
+ readonly loess_fit: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => [number, number];
827
+ readonly loess_predict: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number) => [number, number];
692
828
  readonly make_lambda_path: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number];
693
829
  readonly ols_regression: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number];
694
830
  readonly parse_csv: (a: number, b: number) => [number, number];
@@ -709,6 +845,7 @@ export interface InitOutput {
709
845
  readonly test_housing_regression: () => [number, number];
710
846
  readonly test_r_accuracy: () => [number, number];
711
847
  readonly test_t_critical: (a: number, b: number) => [number, number];
848
+ readonly vif_test: (a: number, b: number, c: number, d: number) => [number, number];
712
849
  readonly white_test: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number];
713
850
  readonly get_t_cdf: (a: number, b: number) => number;
714
851
  readonly get_t_critical: (a: number, b: number) => number;
package/linreg_core.js CHANGED
@@ -170,6 +170,86 @@ export function cooks_distance_test(y_json, x_vars_json) {
170
170
  }
171
171
  }
172
172
 
173
+ /**
174
+ * Performs DFBETAS analysis via WASM.
175
+ *
176
+ * DFBETAS measures the influence of each observation on each regression coefficient.
177
+ * For each observation and each coefficient, it computes the standardized change
178
+ * in the coefficient when that observation is omitted.
179
+ *
180
+ * # Arguments
181
+ *
182
+ * * `y_json` - JSON array of response variable values
183
+ * * `x_vars_json` - JSON array of predictor arrays
184
+ *
185
+ * # Returns
186
+ *
187
+ * JSON string containing the DFBETAS matrix, threshold, and influential observations.
188
+ *
189
+ * # Errors
190
+ *
191
+ * Returns a JSON error object if parsing fails or domain check fails.
192
+ * @param {string} y_json
193
+ * @param {string} x_vars_json
194
+ * @returns {string}
195
+ */
196
+ export function dfbetas_test(y_json, x_vars_json) {
197
+ let deferred3_0;
198
+ let deferred3_1;
199
+ try {
200
+ const ptr0 = passStringToWasm0(y_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
201
+ const len0 = WASM_VECTOR_LEN;
202
+ const ptr1 = passStringToWasm0(x_vars_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
203
+ const len1 = WASM_VECTOR_LEN;
204
+ const ret = wasm.dfbetas_test(ptr0, len0, ptr1, len1);
205
+ deferred3_0 = ret[0];
206
+ deferred3_1 = ret[1];
207
+ return getStringFromWasm0(ret[0], ret[1]);
208
+ } finally {
209
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
210
+ }
211
+ }
212
+
213
+ /**
214
+ * Performs DFFITS analysis via WASM.
215
+ *
216
+ * DFFITS measures the influence of each observation on its own fitted value.
217
+ * It is the standardized change in the fitted value when that observation
218
+ * is omitted from the model.
219
+ *
220
+ * # Arguments
221
+ *
222
+ * * `y_json` - JSON array of response variable values
223
+ * * `x_vars_json` - JSON array of predictor arrays
224
+ *
225
+ * # Returns
226
+ *
227
+ * JSON string containing the DFFITS vector, threshold, and influential observations.
228
+ *
229
+ * # Errors
230
+ *
231
+ * Returns a JSON error object if parsing fails or domain check fails.
232
+ * @param {string} y_json
233
+ * @param {string} x_vars_json
234
+ * @returns {string}
235
+ */
236
+ export function dffits_test(y_json, x_vars_json) {
237
+ let deferred3_0;
238
+ let deferred3_1;
239
+ try {
240
+ const ptr0 = passStringToWasm0(y_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
241
+ const len0 = WASM_VECTOR_LEN;
242
+ const ptr1 = passStringToWasm0(x_vars_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
243
+ const len1 = WASM_VECTOR_LEN;
244
+ const ret = wasm.dffits_test(ptr0, len0, ptr1, len1);
245
+ deferred3_0 = ret[0];
246
+ deferred3_1 = ret[1];
247
+ return getStringFromWasm0(ret[0], ret[1]);
248
+ } finally {
249
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
250
+ }
251
+ }
252
+
173
253
  /**
174
254
  * Performs the Durbin-Watson test for autocorrelation via WASM.
175
255
  *
@@ -492,6 +572,116 @@ export function lasso_regression(y_json, x_vars_json, _variable_names, lambda, s
492
572
  }
493
573
  }
494
574
 
575
+ /**
576
+ * Performs LOESS regression via WASM.
577
+ *
578
+ * LOESS (Locally Estimated Scatterplot Smoothing) is a non-parametric
579
+ * regression method that fits multiple regressions in local subsets
580
+ * of data to create a smooth curve through the data points.
581
+ *
582
+ * # Arguments
583
+ *
584
+ * * `y_json` - JSON array of response variable values
585
+ * * `x_vars_json` - JSON array of predictor arrays
586
+ * * `span` - Fraction of data used in each local fit (0.0 to 1.0)
587
+ * * `degree` - Degree of local polynomial: 0 (constant), 1 (linear), or 2 (quadratic)
588
+ * * `robust_iterations` - Number of robustness iterations (0 for non-robust fit)
589
+ * * `surface` - Surface computation method: "direct" or "interpolate"
590
+ *
591
+ * # Returns
592
+ *
593
+ * JSON string containing:
594
+ * - `fitted` - Fitted values at each observation point
595
+ * - `span` - Span parameter used
596
+ * - `degree` - Degree of polynomial used
597
+ * - `robust_iterations` - Number of robustness iterations performed
598
+ * - `surface` - Surface computation method used
599
+ *
600
+ * # Errors
601
+ *
602
+ * Returns a JSON error object if parsing fails or domain check fails.
603
+ * @param {string} y_json
604
+ * @param {string} x_vars_json
605
+ * @param {number} span
606
+ * @param {number} degree
607
+ * @param {number} robust_iterations
608
+ * @param {string} surface
609
+ * @returns {string}
610
+ */
611
+ export function loess_fit(y_json, x_vars_json, span, degree, robust_iterations, surface) {
612
+ let deferred4_0;
613
+ let deferred4_1;
614
+ try {
615
+ const ptr0 = passStringToWasm0(y_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
616
+ const len0 = WASM_VECTOR_LEN;
617
+ const ptr1 = passStringToWasm0(x_vars_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
618
+ const len1 = WASM_VECTOR_LEN;
619
+ const ptr2 = passStringToWasm0(surface, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
620
+ const len2 = WASM_VECTOR_LEN;
621
+ const ret = wasm.loess_fit(ptr0, len0, ptr1, len1, span, degree, robust_iterations, ptr2, len2);
622
+ deferred4_0 = ret[0];
623
+ deferred4_1 = ret[1];
624
+ return getStringFromWasm0(ret[0], ret[1]);
625
+ } finally {
626
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
627
+ }
628
+ }
629
+
630
+ /**
631
+ * Performs LOESS prediction at new query points via WASM.
632
+ *
633
+ * Predicts LOESS fitted values at arbitrary new points by redoing the
634
+ * local fitting at each query point using the original training data.
635
+ *
636
+ * # Arguments
637
+ *
638
+ * * `new_x_json` - JSON array of new predictor values (p vectors, each of length m)
639
+ * * `original_x_json` - JSON array of original training predictors
640
+ * * `original_y_json` - JSON array of original training response values
641
+ * * `span` - Span parameter (must match the original fit)
642
+ * * `degree` - Degree of polynomial (must match the original fit)
643
+ * * `robust_iterations` - Robustness iterations (must match the original fit)
644
+ * * `surface` - Surface computation method: "direct" or "interpolate"
645
+ *
646
+ * # Returns
647
+ *
648
+ * JSON string containing:
649
+ * - `predictions` - Vector of predicted values at query points
650
+ *
651
+ * # Errors
652
+ *
653
+ * Returns a JSON error object if parsing fails, parameters don't match
654
+ * the original fit, or domain check fails.
655
+ * @param {string} new_x_json
656
+ * @param {string} original_x_json
657
+ * @param {string} original_y_json
658
+ * @param {number} span
659
+ * @param {number} degree
660
+ * @param {number} robust_iterations
661
+ * @param {string} surface
662
+ * @returns {string}
663
+ */
664
+ export function loess_predict(new_x_json, original_x_json, original_y_json, span, degree, robust_iterations, surface) {
665
+ let deferred5_0;
666
+ let deferred5_1;
667
+ try {
668
+ const ptr0 = passStringToWasm0(new_x_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
669
+ const len0 = WASM_VECTOR_LEN;
670
+ const ptr1 = passStringToWasm0(original_x_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
671
+ const len1 = WASM_VECTOR_LEN;
672
+ const ptr2 = passStringToWasm0(original_y_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
673
+ const len2 = WASM_VECTOR_LEN;
674
+ const ptr3 = passStringToWasm0(surface, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
675
+ const len3 = WASM_VECTOR_LEN;
676
+ const ret = wasm.loess_predict(ptr0, len0, ptr1, len1, ptr2, len2, span, degree, robust_iterations, ptr3, len3);
677
+ deferred5_0 = ret[0];
678
+ deferred5_1 = ret[1];
679
+ return getStringFromWasm0(ret[0], ret[1]);
680
+ } finally {
681
+ wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
682
+ }
683
+ }
684
+
495
685
  /**
496
686
  * Generates a lambda path for regularized regression via WASM.
497
687
  *
@@ -1200,6 +1390,53 @@ export function test_t_critical(df, alpha) {
1200
1390
  }
1201
1391
  }
1202
1392
 
1393
+ /**
1394
+ * Performs Variance Inflation Factor (VIF) analysis via WASM.
1395
+ *
1396
+ * VIF measures how much the variance of regression coefficients is inflated
1397
+ * due to multicollinearity among predictor variables. High VIF values indicate
1398
+ * that a predictor is highly correlated with other predictors.
1399
+ *
1400
+ * # Arguments
1401
+ *
1402
+ * * `y_json` - JSON array of response variable values
1403
+ * * `x_vars_json` - JSON array of predictor arrays
1404
+ *
1405
+ * # Returns
1406
+ *
1407
+ * JSON string containing the maximum VIF, detailed VIF results for each predictor,
1408
+ * interpretation, and guidance.
1409
+ *
1410
+ * # Interpretation
1411
+ *
1412
+ * - VIF = 1: No correlation with other predictors
1413
+ * - VIF > 5: Moderate multicollinearity (concerning)
1414
+ * - VIF > 10: High multicollinearity (severe)
1415
+ *
1416
+ * # Errors
1417
+ *
1418
+ * Returns a JSON error object if parsing fails or domain check fails.
1419
+ * @param {string} y_json
1420
+ * @param {string} x_vars_json
1421
+ * @returns {string}
1422
+ */
1423
+ export function vif_test(y_json, x_vars_json) {
1424
+ let deferred3_0;
1425
+ let deferred3_1;
1426
+ try {
1427
+ const ptr0 = passStringToWasm0(y_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1428
+ const len0 = WASM_VECTOR_LEN;
1429
+ const ptr1 = passStringToWasm0(x_vars_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1430
+ const len1 = WASM_VECTOR_LEN;
1431
+ const ret = wasm.vif_test(ptr0, len0, ptr1, len1);
1432
+ deferred3_0 = ret[0];
1433
+ deferred3_1 = ret[1];
1434
+ return getStringFromWasm0(ret[0], ret[1]);
1435
+ } finally {
1436
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
1437
+ }
1438
+ }
1439
+
1203
1440
  /**
1204
1441
  * Performs the White test for heteroscedasticity via WASM.
1205
1442
  *
Binary file
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "Jesse Anderson"
6
6
  ],
7
7
  "description": "Lightweight linear regression (OLS, Ridge, Lasso, Elastic Net) with diagnostic tests. Pure Rust - no external math dependencies.",
8
- "version": "0.4.0",
8
+ "version": "0.5.0",
9
9
  "license": "MIT OR Apache-2.0",
10
10
  "repository": {
11
11
  "type": "git",