From 822da9d6454ae4e49a6564981475b2115c51a421 Mon Sep 17 00:00:00 2001 From: Om-A-osc Date: Thu, 29 Jan 2026 00:21:01 +0530 Subject: [PATCH] feat: add stats/incr/wvariance --- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: passed - task: lint_package_json status: passed - task: lint_repl_help status: passed - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: passed - task: lint_javascript_tests status: passed - task: lint_javascript_benchmarks status: passed - task: lint_python status: passed - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: passed - task: lint_typescript_tests status: passed - task: lint_license_headers status: passed --- --- .../@stdlib/stats/incr/lib/index.js | 9 + .../@stdlib/stats/incr/wvariance/README.md | 163 ++++++++++ .../incr/wvariance/benchmark/benchmark.js | 70 ++++ .../stats/incr/wvariance/docs/repl.txt | 39 +++ .../incr/wvariance/docs/types/index.d.ts | 64 ++++ .../stats/incr/wvariance/docs/types/test.ts | 69 ++++ .../stats/incr/wvariance/examples/index.js | 41 +++ .../@stdlib/stats/incr/wvariance/lib/index.js | 54 ++++ .../@stdlib/stats/incr/wvariance/lib/main.js | 148 +++++++++ .../@stdlib/stats/incr/wvariance/package.json | 64 ++++ .../wvariance/test/fixtures/python/data.json | 302 ++++++++++++++++++ .../wvariance/test/fixtures/python/runner.py | 55 ++++ .../@stdlib/stats/incr/wvariance/test/test.js | 98 ++++++ 13 files changed, 1176 insertions(+) create mode 100644 lib/node_modules/@stdlib/stats/incr/wvariance/README.md create mode 100644 lib/node_modules/@stdlib/stats/incr/wvariance/benchmark/benchmark.js create mode 100644 lib/node_modules/@stdlib/stats/incr/wvariance/docs/repl.txt create mode 100644 lib/node_modules/@stdlib/stats/incr/wvariance/docs/types/index.d.ts create mode 100644 lib/node_modules/@stdlib/stats/incr/wvariance/docs/types/test.ts create mode 100644 lib/node_modules/@stdlib/stats/incr/wvariance/examples/index.js create mode 100644 lib/node_modules/@stdlib/stats/incr/wvariance/lib/index.js create mode 100644 lib/node_modules/@stdlib/stats/incr/wvariance/lib/main.js create mode 100644 lib/node_modules/@stdlib/stats/incr/wvariance/package.json create mode 100644 lib/node_modules/@stdlib/stats/incr/wvariance/test/fixtures/python/data.json create mode 100644 lib/node_modules/@stdlib/stats/incr/wvariance/test/fixtures/python/runner.py create mode 100644 lib/node_modules/@stdlib/stats/incr/wvariance/test/test.js diff --git a/lib/node_modules/@stdlib/stats/incr/lib/index.js b/lib/node_modules/@stdlib/stats/incr/lib/index.js index 8e95b0eca2ac..bbe5051bcd53 100644 --- a/lib/node_modules/@stdlib/stats/incr/lib/index.js +++ b/lib/node_modules/@stdlib/stats/incr/lib/index.js @@ -945,6 +945,15 @@ setReadOnly( ns, 'incrvmr', require( '@stdlib/stats/incr/vmr' ) ); */ setReadOnly( ns, 'incrwmean', require( '@stdlib/stats/incr/wmean' ) ); +/** +* @name incrwvariance +* @memberof ns +* @readonly +* @type {Function} +* @see {@link module:@stdlib/stats/incr/wvariance} +*/ +setReadOnly( ns, 'incrwvariance', require( '@stdlib/stats/incr/wvariance' ) ); + // EXPORTS // diff --git a/lib/node_modules/@stdlib/stats/incr/wvariance/README.md b/lib/node_modules/@stdlib/stats/incr/wvariance/README.md new file mode 100644 index 000000000000..5864b7962c4f --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/wvariance/README.md @@ -0,0 +1,163 @@ + + +# incrwvariance + +> Compute a [weighted variance][weighted-variance] incrementally. + +
+ +The [weighted variance][weighted-variance] is defined as + + + +```math +\sigma^2_w = \frac{\sum_{i=1}^N w_i (x_i - \mu_w)^2}{\sum_{i=1}^N w_i} +``` + + + + + +where `μ_w` is the weighted arithmetic mean. + +
+ + + +
+ +## Usage + +```javascript +var incrwvariance = require( '@stdlib/stats/incr/wvariance' ); +``` + +#### incrwvariance() + +Returns an accumulator `function` which incrementally computes a [weighted variance][weighted-variance]. + +```javascript +var accumulator = incrwvariance(); +``` + +#### accumulator( \[x, w] ) + +If provided an input value `x` and a weight `w`, the accumulator function returns an updated weighted variance. If not provided any input values, the accumulator function returns the current variance. + +```javascript +var accumulator = incrwvariance(); + +var s2 = accumulator( 2.0, 1.0 ); +// returns 0.0 + +s2 = accumulator( 2.0, 0.5 ); +// returns 0.0 + +s2 = accumulator( 3.0, 1.5 ); +// returns 0.25 + +s2 = accumulator(); +// returns 0.25 +``` + +
+ + + +
+ +## Notes + +- Input values are **not** type checked. If provided `NaN` or a value which, when used in computations, results in `NaN`, the accumulated value is `NaN` for **all** future invocations. If non-numeric inputs are possible, you are advised to type check and handle accordingly **before** passing the value to the accumulator function. + +
+ + + +
+ +## Examples + + + +```javascript +var randu = require( '@stdlib/random/base/randu' ); +var incrwvariance = require( '@stdlib/stats/incr/wvariance' ); + +var accumulator; +var v; +var w; +var i; + +// Initialize an accumulator: +accumulator = incrwvariance(); + +// For each simulated datum, update the weighted variance... +for ( i = 0; i < 100; i++ ) { + v = randu() * 100.0; + w = randu() * 100.0; + accumulator( v, w ); +} +console.log( accumulator() ); +``` + +
+ + + + + + + + + + + + + + diff --git a/lib/node_modules/@stdlib/stats/incr/wvariance/benchmark/benchmark.js b/lib/node_modules/@stdlib/stats/incr/wvariance/benchmark/benchmark.js new file mode 100644 index 000000000000..deead6f6a373 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/wvariance/benchmark/benchmark.js @@ -0,0 +1,70 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var randu = require( '@stdlib/random/base/randu' ); +var format = require( '@stdlib/string/format' ); +var pkg = require( './../package.json' ).name; +var incrwvariance = require( './../lib' ); + + +// MAIN // + +bench( pkg, function benchmark( b ) { + var f; + var i; + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + f = incrwvariance(); + if ( typeof f !== 'function' ) { + b.fail( 'should return a function' ); + } + } + b.toc(); + if ( typeof f !== 'function' ) { + b.fail( 'should return a function' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( format( '%s::accumulator', pkg ), function benchmark( b ) { + var acc; + var v; + var i; + + acc = incrwvariance(); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + v = acc( randu(), 1.0 ); + if ( v !== v ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( v !== v ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/lib/node_modules/@stdlib/stats/incr/wvariance/docs/repl.txt b/lib/node_modules/@stdlib/stats/incr/wvariance/docs/repl.txt new file mode 100644 index 000000000000..17476ddaed5d --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/wvariance/docs/repl.txt @@ -0,0 +1,39 @@ + +{{alias}}() + Returns an accumulator function which incrementally computes a weighted + variance. + + If provided arguments, the accumulator function returns an updated weighted + variance. If not provided arguments, the accumulator function returns the + current weighted variance. + + If provided `NaN` or a value which, when used in computations, results in + `NaN`, the accumulated value is `NaN` for all future invocations. + + The accumulator function accepts two arguments: + + - x: value. + - w: weight. + + Returns + ------- + acc: Function + Accumulator function. + + Examples + -------- + > var accumulator = {{alias}}(); + > var s2 = accumulator() + null + > s2 = accumulator( 2.0, 1.0 ) + 0.0 + > s2 = accumulator( 2.0, 0.5 ) + 0.0 + > s2 = accumulator( 3.0, 1.5 ) + 0.25 + > s2 = accumulator() + 0.25 + + See Also + -------- + diff --git a/lib/node_modules/@stdlib/stats/incr/wvariance/docs/types/index.d.ts b/lib/node_modules/@stdlib/stats/incr/wvariance/docs/types/index.d.ts new file mode 100644 index 000000000000..5376c8b753fe --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/wvariance/docs/types/index.d.ts @@ -0,0 +1,64 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// TypeScript Version: 4.1 + +/// + +/** +* If provided both arguments, returns an updated weighted variance; otherwise, returns the current weighted variance. +* +* ## Notes +* +* - If provided `NaN` or a value which, when used in computations, results in `NaN`, the accumulated value is `NaN` for all future invocations. +* +* @param x - value +* @param w - weight +* @returns weighted variance +*/ +type accumulator = ( x?: number, w?: number ) => number | null; + +/** +* Returns an accumulator function which incrementally computes a weighted variance. +* +* @returns accumulator function +* +* @example +* var accumulator = incrwvariance(); +* +* var s2 = accumulator(); +* // returns null +* +* s2 = accumulator( 2.0, 1.0 ); +* // returns 0.0 +* +* s2 = accumulator( 2.0, 0.5 ); +* // returns 0.0 +* +* s2 = accumulator( 3.0, 1.5 ); +* // returns 0.25 +* +* s2 = accumulator(); +* // returns 0.25 +*/ +declare function incrwvariance(): accumulator; + + +// EXPORTS // + +export = incrwvariance; diff --git a/lib/node_modules/@stdlib/stats/incr/wvariance/docs/types/test.ts b/lib/node_modules/@stdlib/stats/incr/wvariance/docs/types/test.ts new file mode 100644 index 000000000000..bd13b52e61cd --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/wvariance/docs/types/test.ts @@ -0,0 +1,69 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import incrwvariance = require( './index' ); + + +// TESTS // + +// The function returns an accumulator function... +{ + incrwvariance(); // $ExpectType accumulator +} + +// The compiler throws an error if the function is provided arguments... +{ + incrwvariance( '5' ); // $ExpectError + incrwvariance( 5 ); // $ExpectError + incrwvariance( true ); // $ExpectError + incrwvariance( false ); // $ExpectError + incrwvariance( null ); // $ExpectError + incrwvariance( undefined ); // $ExpectError + incrwvariance( [] ); // $ExpectError + incrwvariance( {} ); // $ExpectError + incrwvariance( ( x: number ): number => x ); // $ExpectError +} + +// The function returns an accumulator function which returns an accumulated result... +{ + const acc = incrwvariance(); + + acc(); // $ExpectType number | null + acc( 3.14, 1.0 ); // $ExpectType number | null +} + +// The compiler throws an error if the returned accumulator function is provided invalid arguments... +{ + const acc = incrwvariance(); + + acc( '5', 1.0 ); // $ExpectError + acc( true, 1.0 ); // $ExpectError + acc( false, 1.0 ); // $ExpectError + acc( null, 1.0 ); // $ExpectError + acc( [], 1.0 ); // $ExpectError + acc( {}, 1.0 ); // $ExpectError + acc( ( x: number ): number => x, 1.0 ); // $ExpectError + + acc( 3.14, '5' ); // $ExpectError + acc( 3.14, true ); // $ExpectError + acc( 3.14, false ); // $ExpectError + acc( 3.14, null ); // $ExpectError + acc( 3.14, [] ); // $ExpectError + acc( 3.14, {} ); // $ExpectError + acc( 3.14, ( x: number ): number => x ); // $ExpectError +} diff --git a/lib/node_modules/@stdlib/stats/incr/wvariance/examples/index.js b/lib/node_modules/@stdlib/stats/incr/wvariance/examples/index.js new file mode 100644 index 000000000000..9783b4e28891 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/wvariance/examples/index.js @@ -0,0 +1,41 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var randu = require( '@stdlib/random/base/randu' ); +var incrwvariance = require( './../lib' ); + +var accumulator; +var s2; +var x; +var w; +var i; + +// Initialize an accumulator: +accumulator = incrwvariance(); + +// For each simulated datum, update the weighted variance... +console.log( '\nValue\tWeight\tWeighted Variance\n' ); +for ( i = 0; i < 100; i++ ) { + x = randu() * 100.0; + w = randu() * 100.0; + s2 = accumulator( x, w ); + console.log( '%d\t%d\t%d', x.toFixed( 4 ), w.toFixed( 4 ), s2.toFixed( 4 ) ); +} +console.log( '\nFinal weighted variance: %d\n', accumulator() ); diff --git a/lib/node_modules/@stdlib/stats/incr/wvariance/lib/index.js b/lib/node_modules/@stdlib/stats/incr/wvariance/lib/index.js new file mode 100644 index 000000000000..cd7cf749f9da --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/wvariance/lib/index.js @@ -0,0 +1,54 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Compute a weighted variance incrementally. +* +* @module @stdlib/stats/incr/wvariance +* +* @example +* var incrwvariance = require( '@stdlib/stats/incr/wvariance' ); +* +* var accumulator = incrwvariance(); +* +* var s2 = accumulator(); +* // returns null +* +* s2 = accumulator( 2.0, 1.0 ); +* // returns 0.0 +* +* s2 = accumulator( 2.0, 0.5 ); +* // returns 0.0 +* +* s2 = accumulator( 3.0, 1.5 ); +* // returns 0.25 +* +* s2 = accumulator(); +* // returns 0.25 +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/lib/node_modules/@stdlib/stats/incr/wvariance/lib/main.js b/lib/node_modules/@stdlib/stats/incr/wvariance/lib/main.js new file mode 100644 index 000000000000..53d012ca3a34 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/wvariance/lib/main.js @@ -0,0 +1,148 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var isnan = require( '@stdlib/math/base/assert/is-nan' ); + +/** +* Returns an accumulator function which incrementally computes a weighted variance. +* +* ## Method +* +* - The weighted variance is defined as +* +* ```tex +* \sigma_w^2 = \frac{\sum_{i=1}^{n} w_i (x_i - \mu_w)^2}{\sum_{i=1}^{n} w_i} +* ``` +* +* where \\( \mu_w \\) is the weighted arithmetic mean. +* +* - Define the total weight +* +* ```tex +* W_n = \sum_{i=1}^{n} w_i +* ``` +* +* - Define the unnormalized second central moment +* +* ```tex +* S_n = \sum_{i=1}^{n} w_i (x_i - \mu_n)^2 +* ``` +* +* - The weighted variance is obtained by normalizing +* +* ```tex +* \sigma_n^2 = \frac{S_n}{W_n} +* ``` +* +* - The weighted mean is updated incrementally according to +* +* ```tex +* \mu_n = \mu_{n-1} + \frac{w_n}{W_n}(x_n - \mu_{n-1}) +* ``` +* +* - Using this update, the unnormalized variance accumulator satisfies +* +* ```tex +* S_n = S_{n-1} + w_n (x_n - \mu_{n-1})(x_n - \mu_n) +* ``` +* +* which yields a numerically stable, one-pass algorithm for computing the +* weighted variance. +* +* @returns {Function} accumulator function +* +* @example +* var accumulator = incrwvariance(); +* +* var s2 = accumulator(); +* // returns null +* +* s2 = accumulator( 2.0, 1.0 ); +* // returns 0.0 +* +* s2 = accumulator( 2.0, 0.5 ); +* // returns 0.0 +* +* s2 = accumulator( 3.0, 1.5 ); +* // returns 0.25 +* +* s2 = accumulator(); +* // returns 0.25 +*/ +function incrwvariance() { + var poisoned; + var mu; + var W; + var S; + var N; + + N = 0; + W = 0.0; + S = 0.0; + mu = 0.0; + poisoned = false; + + return accumulator; + + /** + * If provided arguments, the accumulator function returns an updated weighted variance. If not provided arguments, the accumulator function returns the current weighted variance. + * + * @private + * @param {number} [x] - value + * @param {number} [w] - weight + * @returns {(number|null)} weighted variance or null + */ + function accumulator( x, w ) { + var muprev; + if ( poisoned ) { + return NaN; + } + + if ( arguments.length === 0 ) { + if ( N === 0 ) { + return null; + } + return S / W; + } + if ( arguments.length !== 2 ) { + poisoned = true; + return NaN; + } + if ( isnan( x ) || isnan( w ) ) { + poisoned = true; + return NaN; + } + + N += 1; + W += w; + muprev = mu; + mu += ( w / W ) * ( x - mu ); + S += w * ( x - muprev ) * ( x - mu ); + if ( N === 1 ) { + return 0.0; + } + return S / W; + } +} + + +// EXPORTS // + +module.exports = incrwvariance; diff --git a/lib/node_modules/@stdlib/stats/incr/wvariance/package.json b/lib/node_modules/@stdlib/stats/incr/wvariance/package.json new file mode 100644 index 000000000000..3c3731d82e31 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/wvariance/package.json @@ -0,0 +1,64 @@ +{ + "name": "@stdlib/stats/incr/wvariance", + "version": "0.0.0", + "description": "Compute a weighted variance incrementally.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "main": "./lib", + "directories": { + "benchmark": "./benchmark", + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "types": "./docs/types", + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "stdmath", + "statistics", + "stats", + "mathematics", + "math", + "variance", + "dispersion", + "incremental", + "accumulator", + "weighted" + ] +} diff --git a/lib/node_modules/@stdlib/stats/incr/wvariance/test/fixtures/python/data.json b/lib/node_modules/@stdlib/stats/incr/wvariance/test/fixtures/python/data.json new file mode 100644 index 000000000000..b564128515de --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/wvariance/test/fixtures/python/data.json @@ -0,0 +1,302 @@ +[ + { + "step": 1, + "x": 3.0471707975443136, + "w": 3.9559294497604784, + "variance": 0.0 + }, + { + "step": 2, + "x": -10.399841062404956, + "w": 3.3577691973009576, + "variance": 44.90315233839998 + }, + { + "step": 3, + "x": 7.5045119580645725, + "w": 3.555310355269042, + "variance": 55.09102587431526 + }, + { + "step": 4, + "x": 9.405647163912139, + "w": 3.925572252007643, + "variance": 56.455245135800695 + }, + { + "step": 5, + "x": -19.510351886538363, + "w": 2.348687300137866, + "variance": 107.32680173840433 + }, + { + "step": 6, + "x": -13.021795068623181, + "w": 2.88683186016918, + "variance": 111.8326745713744 + }, + { + "step": 7, + "x": 1.2784040316728538, + "w": 0.7850052908255215, + "variance": 108.03687128660842 + }, + { + "step": 8, + "x": -3.162425923435822, + "w": 0.6611973603262699, + "variance": 104.75088093868614 + }, + { + "step": 9, + "x": -0.16801157504288794, + "w": 3.3751745127733113, + "variance": 90.93461372403924 + }, + { + "step": 10, + "x": -8.5304392757358, + "w": 2.4083714101013496, + "variance": 86.56665456148613 + }, + { + "step": 11, + "x": 8.793979748628285, + "w": 2.8696569217578256, + "variance": 89.08091132804846 + }, + { + "step": 12, + "x": 7.777919354289483, + "w": 3.8484944013385256, + "variance": 87.2966151572343 + }, + { + "step": 13, + "x": 0.6603069756121605, + "w": 3.2101197680028952, + "variance": 79.83165903313335 + }, + { + "step": 14, + "x": 11.272412069680328, + "w": 2.81253906322418, + "variance": 82.82814070104052 + }, + { + "step": 15, + "x": 4.675093422520456, + "w": 2.8401150876525265, + "variance": 78.36355048817441 + }, + { + "step": 16, + "x": -8.592924628832382, + "w": 1.5893554805068, + "variance": 78.65087778992203 + }, + { + "step": 17, + "x": 3.6875078408249884, + "w": 0.2510073893829031, + "variance": 78.26458088085718 + }, + { + "step": 18, + "x": -9.588826008289988, + "w": 2.239915207238576, + "variance": 79.20319216796995 + }, + { + "step": 19, + "x": 8.784503013072726, + "w": 1.1514648968156933, + "variance": 79.08239437231795 + }, + { + "step": 20, + "x": -0.49925910986252897, + "w": 2.1017903542507175, + "variance": 75.79381310027651 + }, + { + "step": 21, + "x": -1.8486236354526056, + "w": 4.281675059014014, + "variance": 70.15170381185082 + }, + { + "step": 22, + "x": -6.809295444039414, + "w": 1.2463034807401698, + "variance": 69.62016234681343 + }, + { + "step": 23, + "x": 12.225413386740303, + "w": 0.3856834342764235, + "variance": 70.17459541994155 + }, + { + "step": 24, + "x": -1.5452948206880215, + "w": 1.4787810709077833, + "variance": 68.43248754831843 + }, + { + "step": 25, + "x": -4.283278221631072, + "w": 1.5386094130567498, + "variance": 67.10975949693709 + }, + { + "step": 26, + "x": -3.5213355048822956, + "w": 3.343390922161786, + "variance": 64.0959615093746 + }, + { + "step": 27, + "x": 5.323091855533487, + "w": 2.829457546472264, + "variance": 62.63897051522242 + }, + { + "step": 28, + "x": 3.6544406436407835, + "w": 3.9411012246214265, + "variance": 59.820142017832474 + }, + { + "step": 29, + "x": 4.1273261159598835, + "w": 3.355136347604199, + "variance": 57.75725279503625 + }, + { + "step": 30, + "x": 4.308210030078827, + "w": 2.0912956210563456, + "variance": 56.57256059092505 + }, + { + "step": 31, + "x": 21.416476008704613, + "w": 4.08869988486357, + "variance": 75.31070708970952 + }, + { + "step": 32, + "x": -4.064150163846156, + "w": 0.9181673075477492, + "variance": 74.79817682776493 + }, + { + "step": 33, + "x": -5.122427290715374, + "w": 0.21128915835591636, + "variance": 74.71452762533684 + }, + { + "step": 34, + "x": -8.137727282478778, + "w": 0.5412345178006446, + "variance": 74.8248284187793 + }, + { + "step": 35, + "x": 6.159794225754957, + "w": 3.639560817922607, + "variance": 72.5335997693881 + }, + { + "step": 36, + "x": 11.289722927208917, + "w": 2.3631984282317986, + "variance": 73.05658514198716 + }, + { + "step": 37, + "x": -1.1394745765487508, + "w": 0.8902317172646488, + "variance": 72.40179309500343 + }, + { + "step": 38, + "x": -8.401564769625281, + "w": 2.5551193980064815, + "variance": 73.22772067100554 + }, + { + "step": 39, + "x": -8.244812156912396, + "w": 0.8463293032945253, + "variance": 73.42700869660152 + }, + { + "step": 40, + "x": 6.505927878247011, + "w": 3.511969837880907, + "variance": 71.61289776280732 + }, + { + "step": 41, + "x": 7.432541712034423, + "w": 2.2861657503127506, + "variance": 70.69676029190947 + }, + { + "step": 42, + "x": 5.4315426830519495, + "w": 1.9670040078727644, + "variance": 69.54832900795749 + }, + { + "step": 43, + "x": -6.655097072886943, + "w": 1.577409236824595, + "variance": 69.57042768933677 + }, + { + "step": 44, + "x": 2.3216132306671975, + "w": 3.188384706282554, + "variance": 67.43359703515584 + }, + { + "step": 45, + "x": 1.1668580914072821, + "w": 1.8728817917116134, + "variance": 66.23756319343099 + }, + { + "step": 46, + "x": 2.1868859672901295, + "w": 0.5294846046488949, + "variance": 65.90674094211543 + }, + { + "step": 47, + "x": 8.714287779481898, + "w": 0.6782289203905251, + "variance": 65.79701293549093 + }, + { + "step": 48, + "x": 2.2359554877468226, + "w": 4.813298556292621, + "variance": 62.95703448849857 + }, + { + "step": 49, + "x": 6.789135630718949, + "w": 4.552045384467275, + "variance": 61.42895867146031 + }, + { + "step": 50, + "x": 0.6757906948889146, + "w": 3.5285649556726733, + "variance": 59.659440510098804 + } +] diff --git a/lib/node_modules/@stdlib/stats/incr/wvariance/test/fixtures/python/runner.py b/lib/node_modules/@stdlib/stats/incr/wvariance/test/fixtures/python/runner.py new file mode 100644 index 000000000000..f2c5b3b141d4 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/wvariance/test/fixtures/python/runner.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# +# @license Apache-2.0 +# +# Copyright (c) 2026 The Stdlib Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +"""Generate fixture data for testing incremental weighted variance.""" + +import json +import numpy as np + +# reproducibility +rng = np.random.default_rng(42) + +n = 50 # number of samples + +# generate data +x = rng.normal(loc=0.0, scale=10.0, size=n) +w = rng.uniform(0.1, 5.0, size=n) + +records = [] + +for k in range(1, n + 1): + xk = x[:k] + wk = w[:k] + + mu = np.average(xk, weights=wk) + + var = np.average((xk - mu) ** 2, weights=wk) + + records.append({ + "step": k, + "x": float(x[k - 1]), + "w": float(w[k - 1]), + "variance": float(var) + }) + +# write to json +with open("data.json", "w", encoding="utf-8") as f: + json.dump(records, f, indent=2) + +print("data.json written with", n, "records") diff --git a/lib/node_modules/@stdlib/stats/incr/wvariance/test/test.js b/lib/node_modules/@stdlib/stats/incr/wvariance/test/test.js new file mode 100644 index 000000000000..d581b52a0dd4 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/wvariance/test/test.js @@ -0,0 +1,98 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var isAlmostSameValue = require( '@stdlib/assert/is-almost-same-value' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var data = require( './fixtures/python/data.json' ); +var incrwvariance = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof incrwvariance, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function returns an accumulator function', function test( t ) { + t.strictEqual( typeof incrwvariance(), 'function', 'returns expected value' ); + t.end(); +}); + +tape( 'the initial accumulated value is `null`', function test( t ) { + var acc = incrwvariance(); + t.strictEqual( acc(), null, 'returns expected value' ); + t.end(); +}); + +tape( 'the accumulator function incrementally computes a weighted variance', function test( t ) { + var expected; + var actual; + var acc; + var i; + + acc = incrwvariance(); + + for ( i = 0; i < data.length; i++ ) { + expected = data[ i ].variance; + actual = acc( data[ i ].x, data[ i ].w ); + t.strictEqual( isAlmostSameValue( actual, expected, 40.0 ), true, 'within tolerance. x: ' + data[i].x + '. w: ' + data[i].w + '. Value: ' + actual + '. Expected: ' + expected + '.' ); + } + t.end(); +}); + +tape( 'if not provided arguments, the accumulator function returns the current weighted variance', function test( t ) { + var expected = data[ data.length - 1 ].variance; + var acc; + var i; + + acc = incrwvariance(); + for ( i = 0; i < data.length; i++ ) { + acc( data[ i ].x, data[ i ].w ); + } + t.strictEqual( isAlmostSameValue( acc(), expected, 40.0 ), true, 'returns expected value' ); + t.end(); +}); + +tape( 'if not provided a weight, the accumulator function returns `NaN`', function test( t ) { + var acc = incrwvariance(); + t.strictEqual( isnan( acc( 2.0 ) ), true, 'returns expected value' ); + t.strictEqual( isnan( acc( 3.14 ) ), true, 'returns expected value' ); + t.end(); +}); + +tape( 'if provided `NaN` for either a value or a weight, the accumulator function returns `NaN`', function test( t ) { + var acc = incrwvariance(); + t.strictEqual( isnan( acc( 2.0, NaN ) ), true, 'returns expected value' ); + t.strictEqual( isnan( acc( 3.14, NaN ) ), true, 'returns expected value' ); + + acc = incrwvariance(); + t.strictEqual( isnan( acc( NaN, 1.0 ) ), true, 'returns expected value' ); + t.strictEqual( isnan( acc( NaN, 1.0 ) ), true, 'returns expected value' ); + + acc = incrwvariance(); + t.strictEqual( isnan( acc( NaN, NaN ) ), true, 'returns expected value' ); + t.strictEqual( isnan( acc( NaN, NaN ) ), true, 'returns expected value' ); + t.end(); +});