From 6570bf45b7f517c86becccd9648a332b79016f3b Mon Sep 17 00:00:00 2001 From: DivyanshuVorrtex Date: Sat, 6 Dec 2025 17:01:28 +0000 Subject: [PATCH 1/3] =?UTF-8?q?feat(stats/mannwhitneyu):=20add=20Mann?= =?UTF-8?q?=E2=80=93Whitney=20U=20test=20package?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 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: na - task: lint_r status: passed - 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/mannwhitneyu/README.md | 184 +++++++ .../stats/mannwhitneyu/benchmark/benchmark.js | 131 +++++ .../@stdlib/stats/mannwhitneyu/docs/repl.txt | 77 +++ .../stats/mannwhitneyu/docs/types/index.d.ts | 114 +++++ .../stats/mannwhitneyu/docs/types/test.ts | 79 +++ .../stats/mannwhitneyu/examples/index.js | 39 ++ .../@stdlib/stats/mannwhitneyu/lib/index.js | 56 ++ .../@stdlib/stats/mannwhitneyu/lib/main.js | 201 ++++++++ .../@stdlib/stats/mannwhitneyu/lib/print.js | 108 ++++ .../stats/mannwhitneyu/lib/validate.js | 68 +++ .../@stdlib/stats/mannwhitneyu/package.json | 65 +++ .../mannwhitneyu/test/fixtures/r/DESCRIPTION | 9 + .../mannwhitneyu/test/fixtures/r/greater.json | 1 + .../mannwhitneyu/test/fixtures/r/high_p.json | 1 + .../mannwhitneyu/test/fixtures/r/less.json | 1 + .../mannwhitneyu/test/fixtures/r/low_p.json | 1 + .../test/fixtures/r/medium_p.json | 1 + .../mannwhitneyu/test/fixtures/r/runner.R | 129 +++++ .../@stdlib/stats/mannwhitneyu/test/test.js | 479 ++++++++++++++++++ .../stats/mannwhitneyu/test/test.validate.js | 152 ++++++ tools/lint/r/linter.R | 9 +- 21 files changed, 1899 insertions(+), 6 deletions(-) create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/README.md create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/benchmark/benchmark.js create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/docs/repl.txt create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/docs/types/index.d.ts create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/docs/types/test.ts create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/examples/index.js create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/lib/index.js create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/lib/main.js create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/lib/print.js create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/lib/validate.js create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/package.json create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/DESCRIPTION create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/greater.json create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/high_p.json create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/less.json create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/low_p.json create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/medium_p.json create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/runner.R create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/test/test.js create mode 100644 lib/node_modules/@stdlib/stats/mannwhitneyu/test/test.validate.js diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/README.md b/lib/node_modules/@stdlib/stats/mannwhitneyu/README.md new file mode 100644 index 000000000000..8ed8233f04a6 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/README.md @@ -0,0 +1,184 @@ + + +# Mann-Whitney U Test + +> Nonparametric hypothesis test comparing two independent samples. + +
+ +## Usage + +```javascript +var mannWhitneyU = require( '@stdlib/stats/mannwhitneyu' ); +``` + +#### mannWhitneyU( x, y\[, options] ) + +Given two independent samples x and y, the function computes the Mann–Whitney U rank-sum test to assess whether the distributions differ. + +```javascript +var out = mannWhitneyU( [ 7, 8, 9 ], [ 1, 2, 3 ] ); +/* returns + { + 'U': 0, + 'pValue': 0.025, + 'rejected': true + } +*/ + +out = mannWhitneyU( [ 10, 11, 10, 12 ], [ 9, 11, 10, 10 ] ); +/* returns + { + 'U': 4.5, + 'pValue': 0.312, + 'rejected': false + } +*/ +``` + + + +The function accepts the following `options`: + +- **alpha**: `number` in the interval `[0,1]` giving the significance level of the hypothesis test. Default: `0.05`. +- **alternative**: Either `two-sided`, `less` or `greater`. Indicates the direction of the hypothesis test. `'greater'` tests whether values in `x` tend to be larger than those in `y`, `'less'` tests whether values in `x` tend to be smaller than those in `y`, and `'two-sided'` tests for any difference in distributions. + +By default, the hypothesis test is carried out at a significance level of `0.05`. To choose a different significance level, set the `alpha` option. + +```javascript +var out = mannWhitneyU( [ 7, 8, 9 ], [ 1, 2, 3 ], { + 'alpha': 0.05, + 'alternative': 'greater' +}); +/* returns + { + 'U': 0, + 'pValue': 0.025, + 'rejected': true + } +*/ +``` + +By default, a two-sided test is performed. To perform either of the one-sided tests, set the `alternative` option to `less` or `greater`. + +```javascript +out = mannWhitneyU( [ 5, 6, 7, 8 ], [ 1, 2, 3, 4 ], { + 'alternative': 'greater', + 'alpha': 0.05 +}); +/* returns + { + 'U': 0, + 'pValue': 0.0104, + 'rejected': true + } +*/ + +out = mannWhitneyU( [ 5, 6, 7, 8 ], [ 1, 2, 3, 4 ], { + 'alternative': 'less', + 'alpha': 0.05 +}); +/* returns + { + 'U': 0, + 'pValue': 0.9896, + 'rejected': false + } +*/ +``` + +
+ + + +
+ +## Examples + + + +```javascript +var mannWhitneyU = require( '@stdlib/stats/mannwhitneyu' ); + +var x = [ 12, 15, 14, 10, 13 ]; +var y = [ 7, 9, 6, 8, 7 ]; + +var out = mannWhitneyU( x, y ); +/* returns + { + 'U': 0, + 'pValue': 0.009, + 'rejected': true + } +*/ + +out = mannWhitneyU( [ 5, 6, 7, 8 ], [ 1, 2, 3, 4 ] ); +/* returns + { + 'U': 0, + 'pValue': 0.0208, + 'rejected': true + } +*/ + +out = mannWhitneyU( [ 5, 6, 7, 8 ], [ 1, 2, 3, 4 ], { + 'alternative': 'greater' +}); +/* returns + { + 'U': 0, + 'pValue': 0.0104, + 'rejected': true + } +*/ + +out = mannWhitneyU( [ 1, 2, 2, 3 ], [ 2, 3, 4, 5 ], { + 'alternative': 'greater', + 'alpha': 0.05 +}); +/* returns + { + 'U': 2.5, + 'pValue': 0.057, + 'rejected': false + } +*/ +``` + +
+ + + + + + + + + + + + + + diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/benchmark/benchmark.js b/lib/node_modules/@stdlib/stats/mannwhitneyu/benchmark/benchmark.js new file mode 100644 index 000000000000..4e5a450df8f5 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/benchmark/benchmark.js @@ -0,0 +1,131 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 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 isObject = require( '@stdlib/assert/is-object' ); +var isString = require( '@stdlib/assert/is-string' ).isPrimitive; +var discreteUniform = require( '@stdlib/random/base/discrete-uniform' ); +var pkg = require( './../package.json' ).name; +var mannWhitneyU = require( './../lib' ); + + +// MAIN // + +bench( pkg, function benchmark( b ) { + var result; + var x; + var y; + var i; + + x = []; + y = []; + for ( i = 0; i < 100; i++ ) { + x.push( 0 ); + y.push( 0 ); + } + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + fillArray( x ); + fillArray( y ); + result = mannWhitneyU( x, y ); + if ( typeof result !== 'object' ) { + b.fail( 'should return an object' ); + } + } + b.toc(); + if ( !isObject( result ) ) { + b.fail( 'should return an object' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::one-sided', function benchmark( b ) { + var result; + var opts; + var x; + var y; + var i; + + opts = { + 'alternative': 'greater' + }; + x = []; + y = []; + for ( i = 0; i < 100; i++ ) { + x.push( 0 ); + y.push( 0 ); + } + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + fillArray( x ); + fillArray( y ); + result = mannWhitneyU( x, y, opts ); + if ( typeof result !== 'object' ) { + b.fail( 'should return an object' ); + } + } + b.toc(); + if ( !isObject( result ) ) { + b.fail( 'should return an object' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':print', function benchmark( b ) { + var digits; + var result; + var output; + var i; + + result = mannWhitneyU( [ 7, 8, 9 ], [ 1, 2, 3 ] ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + digits = ( i % 8 ) + 1; + output = result.print({ + 'digits': digits + }); + if ( typeof output !== 'string' ) { + b.fail( 'should return a string' ); + } + } + b.toc(); + if ( !isString( output ) ) { + b.fail( 'should return a string' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + + +// FUNCTIONS // + +function fillArray( arr ) { + var i; + for ( i = 0; i < arr.length; i++ ) { + arr[ i ] = discreteUniform( 0, 100 ); + } +} diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/docs/repl.txt b/lib/node_modules/@stdlib/stats/mannwhitneyu/docs/repl.txt new file mode 100644 index 000000000000..32775582920c --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/docs/repl.txt @@ -0,0 +1,77 @@ +{{alias}}( x, y[, options] ) + Computes the Mann–Whitney U rank-sum test for the difference between two + independent samples. + + The returned object comes with a `.print()` method which when invoked will + print a formatted output of the results of the hypothesis test. + + Parameters + ---------- + x: Array + First independent sample. + + y: Array + Second independent sample. + + options: Object (optional) + Options. + + options.alpha: number (optional) + Number in the interval `[0,1]` giving the significance level of the + hypothesis test. Default: `0.05`. + + options.alternative: string (optional) + Indicates whether the alternative hypothesis is that the distribution of + `x` is shifted to the right of `y` (`greater`), to the left of `y` + (`less`) or that they differ (`two-sided`). Default: `'two-sided'`. + + Returns + ------- + out: Object + Test result object. + + out.alpha: number + Used significance level. + + out.rejected: boolean + Test decision. + + out.pValue: number + p-value of the test. + + out.U: number + Mann–Whitney U statistic. + + out.U1: number + U value for sample `x`. + + out.U2: number + U value for sample `y`. + + out.alternative: string + Alternative hypothesis (`two-sided`, `less` or `greater`). + + out.method: string + Name of the test. + + out.print: Function + Function to print formatted output. + + Examples + -------- + > var out = {{alias}}( [ 7, 8, 9 ], [ 1, 2, 3 ] ) + { 'U': 0, 'pValue': ~0.025, ... } + + > out = {{alias}}( [ 5, 6, 7, 8 ], [ 1, 2, 3, 4 ], { + ... 'alternative': 'greater' + ... }) + { 'U': 0, 'pValue': ~0.0104, ... } + + > out = {{alias}}( [ 1, 2, 2, 3 ], [ 2, 3, 4, 5 ], { + ... 'alternative': 'greater', + ... 'alpha': 0.05 + ... }) + { 'U': 2.5, 'pValue': ~0.057, ... } + + See Also + -------- diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/docs/types/index.d.ts b/lib/node_modules/@stdlib/stats/mannwhitneyu/docs/types/index.d.ts new file mode 100644 index 000000000000..997b75a83ff9 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/docs/types/index.d.ts @@ -0,0 +1,114 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2021 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 + +/** +* Interface defining function options. +*/ +interface Options { + /** + * Significance level (default: 0.05). + */ + alpha?: number; + + /** + * Alternative hypothesis (`two-sided`, `less`, or `greater`; default: 'two-sided'). + */ + alternative?: 'two-sided' | 'less' | 'greater'; +} + +/** +* Test result. +*/ +interface Results { + /** + * Used significance level. + */ + alpha: number; + + /** + * Test decision. + */ + rejected: boolean; + + /** + * p-value of the test. + */ + pValue: number; + + /** + * Mann–Whitney U statistic. + */ + U: number; + + /** + * U value for sample x. + */ + U1: number; + + /** + * U value for sample y. + */ + U2: number; + + /** + * Alternative hypothesis (`two-sided`, `less`, or `greater`). + */ + alternative: string; + + /** + * Name of test. + */ + method: string; + + /** + * Function to print formatted output. + */ + print: Function; +} + +/** +* Computes the Mann–Whitney U rank-sum test for two independent samples. +* +* @param x - first sample +* @param y - second sample +* @param options - function options +* @throws must provide valid options +* @returns test results +* +* @example +* var out = mannWhitneyU( [ 7, 8, 9 ], [ 1, 2, 3 ] ); +* // returns {...} +* +* @example +* var out = mannWhitneyU( [ 5, 6, 7, 8 ], [ 1, 2, 3, 4 ], { +* 'alpha': 0.05, +* 'alternative': 'greater' +* }); +* // returns {...} +* +* @example +* mannWhitneyU( [ 1, 2, 3 ], 'invalid' ); +* // throws +*/ +type MannWhitneyU = ( x: Array, y: Array, options?: Options ) => Results; + +declare var mannWhitneyU: MannWhitneyU; + +export = mannWhitneyU; diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/docs/types/test.ts b/lib/node_modules/@stdlib/stats/mannwhitneyu/docs/types/test.ts new file mode 100644 index 000000000000..dc3931b12d5d --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/docs/types/test.ts @@ -0,0 +1,79 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2021 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 mannWhitneyU = require( './index' ); + + +// TESTS // + +// The function returns a test result object... +{ + mannWhitneyU( [ 7, 8, 9 ], [ 1, 2, 3 ] ); // $ExpectType Results + mannWhitneyU( [ 10, 11 ], [ 8, 7 ], { 'alpha': 0.1 } ); // $ExpectType Results + mannWhitneyU( [ 5, 6 ], [ 1, 2 ], { 'alternative': 'greater' } ); // $ExpectType Results +} + +// The compiler throws an error if x is not a numeric array... +{ + mannWhitneyU( 'abc', [ 1, 2 ] ); // $ExpectError + mannWhitneyU( true, [ 1, 2 ] ); // $ExpectError + mannWhitneyU( false, [ 1, 2 ] ); // $ExpectError + mannWhitneyU( null, [ 1, 2 ] ); // $ExpectError + mannWhitneyU( undefined, [ 1, 2 ] ); // $ExpectError + mannWhitneyU( {}, [ 1, 2 ] ); // $ExpectError + mannWhitneyU( [ 'a', 'b' ], [ 1, 2 ] ); // $ExpectError +} + +// The compiler throws an error if y is not a numeric array... +{ + mannWhitneyU( [ 1, 2, 3 ], 'abc' ); // $ExpectError + mannWhitneyU( [ 1, 2, 3 ], true ); // $ExpectError + mannWhitneyU( [ 1, 2, 3 ], null ); // $ExpectError + mannWhitneyU( [ 1, 2, 3 ], undefined ); // $ExpectError + mannWhitneyU( [ 1, 2, 3 ], {} ); // $ExpectError + mannWhitneyU( [ 1, 2, 3 ], [ 'a', 'b' ] ); // $ExpectError +} + +// The compiler throws an error if the options argument is not an object... +{ + mannWhitneyU( [ 1, 2 ], [ 3, 4 ], true ); // $ExpectError + mannWhitneyU( [ 1, 2 ], [ 3, 4 ], 'abc' ); // $ExpectError + mannWhitneyU( [ 1, 2 ], [ 3, 4 ], 123 ); // $ExpectError + mannWhitneyU( [ 1, 2 ], [ 3, 4 ], [] ); // $ExpectError +} + +// The compiler throws an error if the function is provided an `alpha` option that is not a number... +{ + mannWhitneyU( [ 1, 2 ], [ 3, 4 ], { 'alpha': 'abc' } ); // $ExpectError + mannWhitneyU( [ 1, 2 ], [ 3, 4 ], { 'alpha': true } ); // $ExpectError + mannWhitneyU( [ 1, 2 ], [ 3, 4 ], { 'alpha': null } ); // $ExpectError +} + +// The compiler throws an error if the function is provided an `alternative` option which is not a recognized alternative... +{ + mannWhitneyU( [ 1, 2 ], [ 3, 4 ], { 'alternative': 'invalid' } ); // $ExpectError + mannWhitneyU( [ 1, 2 ], [ 3, 4 ], { 'alternative': 123 } ); // $ExpectError + mannWhitneyU( [ 1, 2 ], [ 3, 4 ], { 'alternative': true } ); // $ExpectError +} + +// The compiler throws an error if the function is provided an invalid number of arguments... +{ + mannWhitneyU(); // $ExpectError + mannWhitneyU( [ 1, 2 ] ); // $ExpectError + mannWhitneyU( [ 1, 2 ], [ 3, 4 ], {}, {} ); // $ExpectError +} diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/examples/index.js b/lib/node_modules/@stdlib/stats/mannwhitneyu/examples/index.js new file mode 100644 index 000000000000..b6d3dff96af2 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/examples/index.js @@ -0,0 +1,39 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 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 mannWhitneyU = require( './../lib' ); + +var out = mannWhitneyU( [ 7, 8, 9 ], [ 1, 2, 3 ] ); +console.log( out ); + +out = mannWhitneyU( [ 10, 11, 10, 12 ], [ 9, 11, 10, 10 ] ); +console.log( out ); + +out = mannWhitneyU( [ 7, 8, 9 ], [ 1, 2, 3 ], { + 'alpha': 0.05, + 'alternative': 'greater' +}); +console.log( out ); + +out = mannWhitneyU( [ 5, 6, 7, 8 ], [ 1, 2, 3, 4 ], { + 'alpha': 0.05, + 'alternative': 'less' +}); +console.log( out ); diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/lib/index.js b/lib/node_modules/@stdlib/stats/mannwhitneyu/lib/index.js new file mode 100644 index 000000000000..58b2744f822e --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/lib/index.js @@ -0,0 +1,56 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 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 the Mann–Whitney U rank-sum test for two independent samples. +* +* @module @stdlib/stats/mannwhitneyu +* +* @example +* var mannWhitneyU = require( '@stdlib/stats/mannwhitneyu' ); +* +* var out = mannWhitneyU( [ 7, 8, 9 ], [ 1, 2, 3 ] ); +* // returns +* // { +* 'U': 0, +* 'pValue': 0.025, +* 'rejected': true +* } +* +* out = mannWhitneyU( [ 5, 6, 7, 8 ], [ 1, 2, 3, 4 ], { +* 'alternative': 'greater', +* 'alpha': 0.05 +* }); +* // returns +* // { +* U: 0, +* pValue: 0.0104, +* rejected: true +* } +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/lib/main.js b/lib/node_modules/@stdlib/stats/mannwhitneyu/lib/main.js new file mode 100644 index 000000000000..5d8191e77f5f --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/lib/main.js @@ -0,0 +1,201 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 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 setReadOnly = require( '@stdlib/utils/define-read-only-property' ); +var isNumberArray = require( '@stdlib/assert/is-number-array' ); +var format = require( '@stdlib/string/format' ); +var sqrt = require( '@stdlib/math/base/special/sqrt' ); +var abs = require( '@stdlib/math/base/special/abs' ); +var normalCDF = require( '@stdlib/stats/base/dists/normal/cdf' ); +var min = require( '@stdlib/math/base/special/min' ); +var validate = require( './validate.js' ); + +// eslint-disable-next-line stdlib/no-redeclare +var print = require( './print.js' ); + + +// FUNCTIONS // + +/** +* Comparator for ascending sort of value-index pairs. +* +* @private +* @param {Array} a - first [value, index] pair +* @param {Array} b - second [value, index] pair +* @returns {number} comparison result +*/ +function sortPairs( a, b ) { + return a[ 0 ] - b[ 0 ]; +} + + +// MAIN // + +/** +* Computes the Mann–Whitney U rank-sum test for two independent samples. +* +* @param {NumericArray} x - first sample +* @param {NumericArray} y - second sample +* @param {Options} [options] - function options +* @param {number} [options.alpha=0.05] - significance level +* @param {string} [options.alternative='two-sided'] - alternative hypothesis (`two-sided`, `less`, `greater`) +* @throws {TypeError} must provide two numeric arrays +* @throws {RangeError} alpha option must be a number in `[0,1]` +* @throws {TypeError} alternative option must be a string +* @throws {Error} alternative option must be `two-sided`, `less` or `greater` +* @returns {Object} test results +*/ +function mannWhitneyU() { + var values; + var tieSum; + var pValue; + var alpha; + var ranks; + var pairs; + var opts; + var mean; + var alt; + var avg; + var err; + var out; + var R1; + var U1; + var U2; + var sd; + var n1; + var n2; + var N; + var x; + var y; + var k; + var t; + var U; + var z; + var i; + var j; + + opts = {}; + + x = arguments[ 0 ]; + y = arguments[ 1 ]; + + if ( !isNumberArray( x ) || !isNumberArray( y ) ) { + throw new TypeError( format( 'invalid argument. Must provide two numeric arrays.' ) ); + } + n1 = x.length; + n2 = y.length; + N = n1 + n2; + + if ( arguments[ 2 ] ) { + err = validate( opts, arguments[ 2 ] ); + } + if ( err ) { + throw err; + } + + alpha = ( opts.alpha === void 0 ) ? 0.05 : opts.alpha; + alt = opts.alternative || 'two-sided'; + + values = x.concat( y ); + + pairs = []; + for ( i = 0; i < N; i++ ) { + pairs.push( [ values[ i ], i ] ); + } + + pairs.sort( sortPairs ); + + ranks = []; + tieSum = 0.0; + + i = 0; + while ( i < N ) { + j = i + 1; + + while ( j < N && pairs[ j ][ 0 ] === pairs[ i ][ 0 ] ) { + j += 1; + } + t = j - i; + avg = ( i + j + 1 ) / 2.0; + + for ( k = i; k < j; k++ ) { + ranks[ pairs[ k ][ 1 ] ] = avg; + } + if ( t > 1 ) { + tieSum += ( t * t * t ) - t; + } + i = j; + } + + R1 = 0.0; + for ( i = 0; i < n1; i++ ) { + R1 += ranks[ i ]; + } + + U1 = R1 - ( n1 * ( n1 + 1 ) * 0.5 ); + U2 = ( n1 * n2 ) - U1; + + if ( alt === 'two-sided' ) { + U = min( U1, U2 ); + } else { + U = U1; + } + + mean = n1 * n2 * 0.5; + + if ( tieSum === 0.0 ) { + sd = sqrt( ( n1 * n2 * ( N + 1 ) ) / 12.0 ); + } else { + // eslint-disable-next-line max-len + sd = sqrt( ( n1 * n2 / 12.0 ) * ( ( N + 1 ) - ( tieSum / ( N * ( N - 1 ) ) ) ) ); + } + + z = ( U - mean ) / sd; + + if ( alt === 'two-sided' ) { + pValue = 2.0 * ( 1.0 - normalCDF( abs( z ), 0.0, 1.0 ) ); + } else if ( alt === 'greater' ) { + pValue = 1.0 - normalCDF( z, 0.0, 1.0 ); + } else if ( alt === 'less' ) { + pValue = normalCDF( z, 0.0, 1.0 ); + } else { + throw new Error(format('invalid option. `%s` option must be one of `two-sided`, `less`, `greater`. Option: `%s`.', 'alternative', alt)); + } + + out = {}; + setReadOnly( out, 'U', U ); + setReadOnly( out, 'U1', U1 ); + setReadOnly( out, 'U2', U2 ); + setReadOnly( out, 'pValue', pValue ); + setReadOnly( out, 'rejected', pValue <= alpha ); + setReadOnly( out, 'alpha', alpha ); + setReadOnly( out, 'alternative', alt ); + setReadOnly( out, 'method', 'Mann–Whitney U test' ); + setReadOnly( out, 'print', print ); + + return out; +} + + +// EXPORTS // + +module.exports = mannWhitneyU; diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/lib/print.js b/lib/node_modules/@stdlib/stats/mannwhitneyu/lib/print.js new file mode 100644 index 000000000000..49cb1b8c85d7 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/lib/print.js @@ -0,0 +1,108 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 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 isPositiveInteger = require( '@stdlib/assert/is-positive-integer' ); +var isObject = require( '@stdlib/assert/is-plain-object' ); +var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive; +var hasOwnProp = require( '@stdlib/assert/has-own-property' ); +var roundn = require( '@stdlib/math/base/special/roundn' ); +var format = require( '@stdlib/string/format' ); + + +// MAIN // + +/** +* Pretty-print output of test. +* +* @param {Object} [opts] - options object +* @param {PositiveInteger} [opts.digits=4] - number of digits after decimal point +* @param {boolean} [opts.decision=true] - whether to print the test decision +* @throws {TypeError} options argument must be an object +* @throws {TypeError} must provide valid options +* @returns {string} formatted output +*/ +function print( opts ) { // eslint-disable-line stdlib/no-redeclare + /* eslint-disable no-invalid-this */ + var decision; + var dgts; + var str; + + dgts = 4; + decision = true; + + if ( arguments.length > 0 ) { + if ( !isObject( opts ) ) { + throw new TypeError( format( 'invalid argument. First argument must be an object. Value: `%s`.', opts ) ); + } + if ( hasOwnProp( opts, 'digits' ) ) { + if ( !isPositiveInteger( opts.digits ) ) { + throw new TypeError( format( 'invalid option. `%s` option must be a positive integer. Option: `%s`.', 'digits', opts.digits ) ); + } + dgts = opts.digits; + } + if ( hasOwnProp( opts, 'decision' ) ) { + if ( !isBoolean( opts.decision ) ) { + throw new TypeError( format( 'invalid option. `%s` option must be a boolean. Option: `%s`.', 'decision', opts.decision ) ); + } + decision = opts.decision; + } + } + + str = ''; + str += this.method + '\n\n'; + str += 'Alternative hypothesis: '; + str += 'Distribution of sample x is '; + + switch ( this.alternative ) { + case 'less': + str += 'less than '; + break; + case 'greater': + str += 'greater than '; + break; + case 'two-sided': + default: + str += 'different from '; + break; + } + str += 'distribution of sample y\n\n'; + + str += ' U statistic: ' + roundn( this.U, -dgts ) + '\n'; + str += ' pValue: ' + roundn( this.pValue, -dgts ) + '\n\n'; + + if ( decision ) { + str += 'Test Decision: '; + if ( this.rejected ) { + str += 'Reject null hypothesis at ' + ( this.alpha * 100 ) + '% significance level'; + } else { + str += 'Fail to reject null hypothesis at ' + ( this.alpha * 100 ) + '% significance level'; + } + str += '\n'; + } + + return str; +} + + +// EXPORTS // + +module.exports = print; diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/lib/validate.js b/lib/node_modules/@stdlib/stats/mannwhitneyu/lib/validate.js new file mode 100644 index 000000000000..1f7e88b873c6 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/lib/validate.js @@ -0,0 +1,68 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 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 isNumber = require( '@stdlib/assert/is-number' ).isPrimitive; +var isObject = require( '@stdlib/assert/is-plain-object' ); +var isString = require( '@stdlib/assert/is-string' ).isPrimitive; +var isnan = require( '@stdlib/assert/is-nan' ); +var hasOwnProp = require( '@stdlib/assert/has-own-property' ); +var format = require( '@stdlib/string/format' ); + + +// MAIN // + +/** +* Validates function options. +* +* @private +* @param {Object} opts - destination for validated options +* @param {Options} options - function options +* @param {number} [options.alpha] - significance level +* @param {string} [options.alternative] - alternative hypothesis (`two-sided`, `less`, `greater`) +* @returns {(null|Error)} null or an error +*/ +function validate( opts, options ) { + if ( !isObject( options ) ) { + return new TypeError( format( 'invalid argument. Options argument must be an object. Value: `%s`.', options ) ); + } + if ( hasOwnProp( options, 'alpha' ) ) { + opts.alpha = options.alpha; + if ( !isNumber( opts.alpha ) || isnan( opts.alpha ) ) { + return new TypeError( format( 'invalid option. `%s` option must be a number. Option: `%s`.', 'alpha', opts.alpha ) ); + } + if ( opts.alpha < 0.0 || opts.alpha > 1.0 ) { + return new RangeError( format( 'invalid option. `%s` option must be a number in the interval: [0, 1]. Option: `%s`.', 'alpha', opts.alpha ) ); + } + } + if ( hasOwnProp( options, 'alternative' ) ) { + opts.alternative = options.alternative; + if ( !isString( opts.alternative ) ) { + return new TypeError( format( 'invalid option. `%s` option must be a string. Option: `%s`.', 'alternative', opts.alternative ) ); + } + } + return null; +} + + +// EXPORTS // + +module.exports = validate; diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/package.json b/lib/node_modules/@stdlib/stats/mannwhitneyu/package.json new file mode 100644 index 000000000000..1d4a1640a0b0 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/package.json @@ -0,0 +1,65 @@ +{ + "name": "@stdlib/stats/mannwhitneyu", + "version": "0.0.0", + "description": "Mann–Whitney U test for comparing two independent samples.", + "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", + "stats", + "statistics", + "math", + "mann-whitney", + "u-test", + "ranksum", + "hypothesis", + "nonparametric", + "independent", + "u-statistic", + "p-value" + ] +} diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/DESCRIPTION b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/DESCRIPTION new file mode 100644 index 000000000000..902d9146b6bf --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/DESCRIPTION @@ -0,0 +1,9 @@ +Package: mannwhitneyu-fixtures +Title: Test Fixtures +Version: 0.0.0 +Authors@R: person("stdlib", "js", role = c("aut","cre")) +Description: Generates Mann-Whitney U test fixtures using wilcox.test() in R. +Depends: R (>= 3.4.0) +Imports: + jsonlite +LazyData: true diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/greater.json b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/greater.json new file mode 100644 index 000000000000..fabfc76ca2b1 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/greater.json @@ -0,0 +1 @@ +{"x":[5,6,7,8],"y":[4,5,6,7],"U":11.5,"pValue":0.15176256166717603,"alternative":"greater","alpha":0.050000000000000003,"rejected":false} diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/high_p.json b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/high_p.json new file mode 100644 index 000000000000..c8d3e1311a1f --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/high_p.json @@ -0,0 +1 @@ +{"x":[10,11,12,13,14],"y":[1,2,3,4,5],"U":0,"pValue":0.0090234388180803291,"alternative":"two-sided","alpha":0.050000000000000003,"rejected":true} diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/less.json b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/less.json new file mode 100644 index 000000000000..db8a7234ca75 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/less.json @@ -0,0 +1 @@ +{"x":[5,6,7,8],"y":[6,7,8,9],"U":4.5,"pValue":0.15176256166717603,"alternative":"less","alpha":0.050000000000000003,"rejected":false} diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/low_p.json b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/low_p.json new file mode 100644 index 000000000000..97cfa391490b --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/low_p.json @@ -0,0 +1 @@ +{"x":[5,6,7,8],"y":[6,7,8,9],"U":4.5,"pValue":0.30352512333435205,"alternative":"two-sided","alpha":0.050000000000000003,"rejected":false} diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/medium_p.json b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/medium_p.json new file mode 100644 index 000000000000..9ed8fd555127 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/medium_p.json @@ -0,0 +1 @@ +{"x":[5,6,7,8],"y":[4,5,6,7],"U":4.5,"pValue":0.30352512333435205,"alternative":"two-sided","alpha":0.050000000000000003,"rejected":false} diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/runner.R b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/runner.R new file mode 100644 index 000000000000..69cc8bb4bb5a --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/runner.R @@ -0,0 +1,129 @@ +#!/usr/bin/env Rscript +# +# @license Apache-2.0 +# +# Copyright (c) 2018 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. + +# Set the precision to 16 digits: +options( digits = 16L ); + +#' Generate test fixtures. +#' +#' @examples +#' main(); +main <- function() { + #' Get the script filepath. + #' + #' @return The absolute path of this script + #' + #' @examples + #' filepath <- get_script_path(); + get_script_path <- function() { + args <- commandArgs( trailingOnly = FALSE ); + needle <- '--file='; + match <- grep( needle, args ); + if ( length( match ) > 0L ) { + # Rscript: + filepath <- sub( needle, '', args[match] ); + } else { + ls_vars <- ls( sys.frames()[[1L]] ) + if ( 'fileName' %in% ls_vars ) { + # Source'd via RStudio: + filepath <- sys.frames()[[1L]]$fileName; # nolint + } else { + # Source'd via R console: + filepath <- sys.frames()[[1L]]$ofile; + } + } + return( normalizePath( filepath ) ); + } + + #' Convert a data structure to JSON. + #' + #' @param x A data structure to convert + #' @return JSON blob + #' + #' @examples + #' x <- seq( -6.5, 25, 0.5 ); + #' json <- to_json( x ); + to_json <- function( x ) { + return( jsonlite::toJSON( x, digits = 16L, auto_unbox = TRUE ) ); + } + + #' Generate an output absolute filepath based on the script directory. + #' + #' @param name An output filename + #' @return An absolute filepath + #' + #' @examples + #' filepath <- get_filepath( 'data.json' ); + get_filepath <- function( name ) { + return( paste( source_dir, '/', name, sep = '' ) ); + } + + # Get the directory of this script: + source_dir <- dirname( get_script_path() ); + + # Generate test fixture data: + # Note: We set exact=FALSE to force normal approximation matching JS implementation. + high_p_res <- wilcox.test( c( 10.0, 11.0, 12.0, 13.0, 14.0 ), c( 1.0, 2.0, 3.0, 4.0, 5.0 ), alternative = 'two.sided', correct = FALSE, exact = FALSE ); + u_high <- min( high_p_res$statistic, ( 5.0 * 5.0 ) - high_p_res$statistic ); + high_p <- list( x = c( 10.0, 11.0, 12.0, 13.0, 14.0 ), y = c( 1.0, 2.0, 3.0, 4.0, 5.0 ), U = u_high, pValue = high_p_res$p.value, alternative = 'two-sided', alpha = 0.05, + rejected = high_p_res$p.value <= 0.05 ); + + medium_p_res <- wilcox.test( c( 5.0, 6.0, 7.0, 8.0 ), c( 4.0, 5.0, 6.0, 7.0 ), alternative = 'two.sided', correct = FALSE, exact = FALSE ); + u_med <- min( medium_p_res$statistic, ( 4.0 * 4.0 ) - medium_p_res$statistic ); + medium_p <- list( x = c( 5.0, 6.0, 7.0, 8.0 ), y = c( 4.0, 5.0, 6.0, 7.0 ), U = u_med, pValue = medium_p_res$p.value, alternative = 'two-sided', alpha = 0.05, + rejected = medium_p_res$p.value <= 0.05 ); + + low_p_res <- wilcox.test( c( 5.0, 6.0, 7.0, 8.0 ), c( 6.0, 7.0, 8.0, 9.0 ), alternative = 'two.sided', correct = FALSE, exact = FALSE ); + u_low <- min( low_p_res$statistic, ( 4.0 * 4.0 ) - low_p_res$statistic ); + low_p <- list( x = c( 5.0, 6.0, 7.0, 8.0 ), y = c( 6.0, 7.0, 8.0, 9.0 ), U = u_low, pValue = low_p_res$p.value, alternative = 'two-sided', alpha = 0.05, + rejected = low_p_res$p.value <= 0.05 ); + + less <- wilcox.test( c( 5.0, 6.0, 7.0, 8.0 ), c( 6.0, 7.0, 8.0, 9.0 ), alternative = 'less', correct = FALSE, exact = FALSE ); + less <- list( x = c( 5.0, 6.0, 7.0, 8.0 ), y = c( 6.0, 7.0, 8.0, 9.0 ), U = less$statistic, pValue = less$p.value, alternative = 'less', alpha = 0.05, + rejected = less$p.value <= 0.05 ); + + greater <- wilcox.test( c( 5.0, 6.0, 7.0, 8.0 ), c( 4.0, 5.0, 6.0, 7.0 ), alternative = 'greater', correct = FALSE, exact = FALSE ); + greater <- list( x = c( 5.0, 6.0, 7.0, 8.0 ), y = c( 4.0, 5.0, 6.0, 7.0 ), U = greater$statistic, pValue = greater$p.value, alternative = 'greater', alpha = 0.05, + rejected = greater$p.value <= 0.05 ); + + # Convert fixture data to JSON: + high_p <- to_json( high_p ); + medium_p <- to_json( medium_p ); + low_p <- to_json( low_p ); + less <- to_json( less ); + greater <- to_json( greater ); + + + # Write the data to file... + filepath <- get_filepath( 'high_p.json' ); + write( high_p, filepath ); + + filepath <- get_filepath( 'medium_p.json' ); + write( medium_p, filepath ); + + filepath <- get_filepath( 'low_p.json' ); + write( low_p, filepath ); + + filepath <- get_filepath( 'less.json' ); + write( less, filepath ); + + filepath <- get_filepath( 'greater.json' ); + write( greater, filepath ); +} + +main(); diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/test/test.js b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/test.js new file mode 100644 index 000000000000..751fdcf9089d --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/test.js @@ -0,0 +1,479 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 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 contains = require( '@stdlib/assert/contains' ); +var abs = require( '@stdlib/math/base/special/abs' ); +var EPS = require( '@stdlib/constants/float64/eps' ); +var mannWhitneyU = require( './../lib' ); + + +// FIXTURES // + +var highP = require( './fixtures/r/high_p.json' ); +var mediumP = require( './fixtures/r/medium_p.json' ); +var lowP = require( './fixtures/r/low_p.json' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof mannWhitneyU, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function throws an error if the `x` argument is not a numeric array', function test( t ) { + var values; + var i; + + values = [ + '5', + 5, + true, + void 0, + null, + NaN, + function noop() {}, + {} + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + mannWhitneyU( value, [ 1, 2, 3 ] ); + }; + } +}); + +tape( 'the function throws an error if the `y` argument is not a numeric array', function test( t ) { + var values; + var i; + + values = [ + '5', + 5, + true, + void 0, + null, + NaN, + function noop() {}, + {} + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + mannWhitneyU( [ 1, 2, 3 ], value ); + }; + } +}); + +tape( 'the function throws an error if provided an invalid `alternative` option', function test( t ) { + var values; + var i; + + values = [ + 5, + true, + void 0, + null, + NaN, + [], + {} + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] ); + } + + t.throws( badValue( 'not one of less, greater or two-sided' ), Error, 'throws an error when provided not less, greater or two-sided' ); + t.end(); + + function badValue( value ) { + return function badValue() { + mannWhitneyU( [ 1, 2, 3 ], [ 1, 2, 3 ], { + 'alternative': value + }); + }; + } +}); + +tape( 'the function throws an error if the `alpha` option is a numeric value outside `[0,1]`', function test( t ) { + var values; + var i; + + values = [ + 1.1, + -0.1 + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), RangeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + mannWhitneyU( [ 1, 2, 3 ], [ 1, 2, 3 ], { + 'alpha': value + }); + }; + } +}); + +tape( 'the function performs a Mann-Whitney U test (high `p`)', function test( t ) { + var expected; + var delta; + var out; + var tol; + var x; + var y; + + x = highP.x; + y = highP.y; + out = mannWhitneyU( x, y ); + + // Tested against R: + expected = highP.pValue; + delta = abs( out.pValue - expected ); + tol = 50.0 * EPS * abs( expected ); + t.ok( delta <= tol, 'within tolerance. x: '+x+'. y: '+y+'. pValue: '+out.pValue+'. E: '+expected+'. Δ: '+delta+'. tol: '+tol ); + + expected = highP.U; + t.strictEqual( out.U, expected, 'returns expected U statistic' ); + + t.strictEqual( out.rejected, highP.rejected, 'returns expected rejected status' ); + + t.end(); +}); + +tape( 'the function performs a Mann-Whitney U test (medium `p`)', function test( t ) { + var expected; + var delta; + var out; + var tol; + var x; + var y; + + x = mediumP.x; + y = mediumP.y; + out = mannWhitneyU( x, y ); + + // Tested against R: + expected = mediumP.pValue; + delta = abs( out.pValue - expected ); + tol = 120.0 * EPS * abs( expected ); + t.ok( delta <= tol, 'within tolerance. x: '+x+'. y: '+y+'. pValue: '+out.pValue+'. E: '+expected+'. Δ: '+delta+'. tol: '+tol ); + + expected = mediumP.U; + t.strictEqual( out.U, expected, 'returns expected U statistic' ); + + t.strictEqual( out.rejected, mediumP.rejected, 'returns expected rejected status' ); + + t.end(); +}); + +tape( 'the function performs a Mann-Whitney U test (low `p`)', function test( t ) { + var expected; + var delta; + var out; + var tol; + var x; + var y; + + x = lowP.x; + y = lowP.y; + out = mannWhitneyU( x, y ); + + // Tested against R: + expected = lowP.pValue; + delta = abs( out.pValue - expected ); + tol = 50.0 * EPS * abs( expected ); + t.ok( delta <= tol, 'within tolerance. x: '+x+'. y: '+y+'. pValue: '+out.pValue+'. E: '+expected+'. Δ: '+delta+'. tol: '+tol ); + + expected = lowP.U; + t.strictEqual( out.U, expected, 'returns expected U statistic' ); + + t.strictEqual( out.rejected, lowP.rejected, 'returns expected rejected status' ); + + t.end(); +}); + +tape( 'the function performs a Mann-Whitney U test (alternative `less`)', function test( t ) { + var expected; + var delta; + var less; + var out; + var tol; + var x; + var y; + + less = require( './fixtures/r/less.json' ); + x = less.x; + y = less.y; + out = mannWhitneyU( x, y, { + 'alternative': 'less' + }); + + expected = less.pValue; + delta = abs( out.pValue - expected ); + tol = 50.0 * EPS * abs( expected ); + t.ok( delta <= tol, 'within tolerance. x: '+x+'. y: '+y+'. pValue: '+out.pValue+'. E: '+expected+'. Δ: '+delta+'. tol: '+tol ); + + expected = less.U; + t.strictEqual( out.U, expected, 'returns expected U statistic' ); + + t.strictEqual( out.rejected, less.rejected, 'returns expected rejected status' ); + + t.end(); +}); + +tape( 'the function performs a Mann-Whitney U test (alternative `greater`)', function test( t ) { + var expected; + var greater; + var delta; + var out; + var tol; + var x; + var y; + + greater = require( './fixtures/r/greater.json' ); + x = greater.x; + y = greater.y; + out = mannWhitneyU( x, y, { + 'alternative': 'greater' + }); + + expected = greater.pValue; + delta = abs( out.pValue - expected ); + tol = 50.0 * EPS * abs( expected ); + t.ok( delta <= tol, 'within tolerance. x: '+x+'. y: '+y+'. pValue: '+out.pValue+'. E: '+expected+'. Δ: '+delta+'. tol: '+tol ); + + expected = greater.U; + t.strictEqual( out.U, expected, 'returns expected U statistic' ); + + t.strictEqual( out.rejected, greater.rejected, 'returns expected rejected status' ); + + t.end(); +}); + +tape( 'the function returns an object with a `.print()` method for generating a formatted output of results', function test( t ) { + var table; + var out; + var x; + var y; + + x = [ 1, 2, 3 ]; + y = [ 4, 5, 6 ]; + + out = mannWhitneyU( x, y ); + table = out.print(); + t.strictEqual( typeof table, 'string', 'returns a pretty-printed table' ); + + out = mannWhitneyU( x, y, { + 'alternative': 'less' + }); + table = out.print(); + t.strictEqual( typeof table, 'string', 'returns a pretty-printed table' ); + + out = mannWhitneyU( x, y, { + 'alternative': 'greater' + }); + table = out.print(); + t.strictEqual( typeof table, 'string', 'returns a pretty-printed table' ); + t.end(); +}); + +tape( 'the function returns an object with a `.print()` method that accepts a `digits` option to control the number of decimal digits displayed', function test( t ) { + var table; + var out; + var x; + var y; + + x = [ 1, 2, 3 ]; + y = [ 4, 5, 6 ]; + + out = mannWhitneyU( x, y ); + table = out.print({ + 'digits': 6 + }); + t.strictEqual( typeof table, 'string', 'returns a pretty-printed table' ); + t.end(); +}); + +tape( 'the function returns an object with a `.print()` method that accepts a `decision` option to control whether the test result should be displayed', function test( t ) { + var table; + var out; + var x; + var y; + + x = [ 1, 2, 3 ]; + y = [ 4, 5, 6 ]; + + out = mannWhitneyU( x, y ); + table = out.print({ + 'decision': false + }); + t.strictEqual( typeof table, 'string', 'returns a pretty-printed table' ); + t.strictEqual( contains( table, 'Test Decision' ), false, 'table does not contain test decision' ); + t.end(); +}); + +tape( 'the function returns an object with a `.print()` method that accepts an `options` object', function test( t ) { + var table; + var out; + var x; + var y; + + x = [ 1, 2, 3 ]; + y = [ 4, 5, 6 ]; + + out = mannWhitneyU( x, y ); + table = out.print( {} ); + + t.strictEqual( typeof table, 'string', 'returns a pretty-printed table' ); + t.end(); +}); + +tape( 'the function returns an object with a `.print()` method that throws an error if `options` is not a simple object', function test( t ) { + var values; + var out; + var i; + var x; + var y; + + x = [ 1, 2, 3 ]; + y = [ 4, 5, 6 ]; + + out = mannWhitneyU( x, y ); + + values = [ + 'abc', + 4, + null, + true, + void 0, + NaN, + [], + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + out.print( value ); + }; + } +}); + +tape( 'the function returns an object with a `.print()` method that throws an error if the `digits` option is not a positive integer', function test( t ) { + var values; + var out; + var i; + var x; + var y; + + x = [ 1, 2, 3 ]; + y = [ 4, 5, 6 ]; + + out = mannWhitneyU( x, y ); + + values = [ + 'abc', + 2.4, + 0.0, + -1.0, + null, + true, + void 0, + NaN, + [], + {}, + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + out.print({ + 'digits': value + }); + }; + } +}); + +tape( 'the function returns an object with a `.print()` method that throws an error if the `decision` option is not a boolean primitive', function test( t ) { + var values; + var out; + var i; + var x; + var y; + + x = [ 1, 2, 3 ]; + y = [ 4, 5, 6 ]; + + out = mannWhitneyU( x, y ); + + values = [ + 'abc', + 2.4, + 0.0, + -1.0, + null, + 8.0, + void 0, + NaN, + [], + {}, + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + out.print({ + 'decision': value + }); + }; + } +}); diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/test/test.validate.js b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/test.validate.js new file mode 100644 index 000000000000..3d2fea3b883c --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/test.validate.js @@ -0,0 +1,152 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 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 validate = require( './../lib/validate.js' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof validate, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function returns a type error if not provided an options object', function test( t ) { + var values; + var err; + var i; + + values = [ + '5', + 5, + NaN, + true, + null, + void 0, + [], + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + err = validate( {}, values[i] ); + t.strictEqual( err instanceof TypeError, true, 'returns a TypeError when provided '+values[i] ); + } + t.end(); +}); + +tape( 'the function returns a type error if provided a `alpha` option which is not a `number` primitive', function test( t ) { + var values; + var err; + var i; + + values = [ + '5', + false, + NaN, + null, + void 0, + [], + {}, + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + err = validate( {}, { + 'alpha': values[i] + }); + t.strictEqual( err instanceof TypeError, true, 'returns a TypeError when provided '+values[i] ); + } + t.end(); +}); + +tape( 'the function returns a type error if provided an `alternative` option which is not a `string` primitive', function test( t ) { + var values; + var err; + var i; + + values = [ + 5, + NaN, + true, + null, + void 0, + [], + {}, + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + err = validate( {}, { + 'alternative': values[i] + }); + t.strictEqual( err instanceof TypeError, true, 'returns a TypeError when provided '+values[i] ); + } + t.end(); +}); + +tape( 'the function returns `null` if all options are valid', function test( t ) { + var expected; + var options; + var opts; + var err; + + options = { + 'alternative': 'greater', + 'alpha': 0.05 + }; + opts = {}; + + expected = { + 'alternative': options.alternative, + 'alpha': options.alpha + }; + + err = validate( opts, options ); + + t.strictEqual( err, null, 'returns expected value' ); + t.deepEqual( opts, expected, 'extracts options' ); + + t.end(); +}); + +tape( 'the function ignores unrecognized options', function test( t ) { + var options; + var opts; + var err; + + options = { + 'beep': 'boop', + 'foo': 5, + 'bar': {} + }; + + opts = {}; + + err = validate( opts, options ); + + t.strictEqual( err, null, 'returns expected value' ); + t.deepEqual( opts, {}, 'ignores unrecognized options' ); + + t.end(); +}); diff --git a/tools/lint/r/linter.R b/tools/lint/r/linter.R index db9905591700..435cf55fa9f9 100644 --- a/tools/lint/r/linter.R +++ b/tools/lint/r/linter.R @@ -25,7 +25,7 @@ # [1]: https://github.com/jimhester/lintr # Ensure that the `lintr` package is installed... -if ( !require( 'lintr', quietly = TRUE, character.only = TRUE ) ) { +if ( !requireNamespace( 'lintr', quietly = TRUE ) ) { install.packages( 'lintr', repos = 'http://lib.stat.cmu.edu/R/CRAN/', quiet = TRUE ); } @@ -39,7 +39,7 @@ if ( n == 0L ) { } # Specify which linters to use... -linters <- lintr::linters_with_defaults( defaults = default_linters, +linters <- lintr::linters_with_defaults( defaults = lintr::default_linters, # Check that no absolute paths are used: absolute_path_linter = lintr::absolute_path_linter(), @@ -52,9 +52,6 @@ linters <- lintr::linters_with_defaults( defaults = default_linters, # Allow commented code outside roxygen blocks: commented_code_linter = NULL, # lintr::commented_code_linter, - # Require the `[[` operator is used when extracting a single element from an object, not `[` (subsetting) or `$` (interactive use): - extraction_operator_linter = lintr::extraction_operator_linter(), - # Require that integers are explicitly typed using the form `1L` instead of `1`: implicit_integer_linter = lintr::implicit_integer_linter(), @@ -111,7 +108,7 @@ linters <- lintr::linters_with_defaults( defaults = default_linters, T_and_F_symbol_linter = lintr::T_and_F_symbol_linter(), # Report the use of undesirable functions (e.g., `attach` or `sapply`) and suggest an alternative: - undesirable_function_linter = lintr::undesirable_function_linter( fun = within( default_undesirable_functions, rm( options ) ) ), + undesirable_function_linter = lintr::undesirable_function_linter( fun = within( lintr::default_undesirable_functions, rm( options ) ) ), # Report the use of undesirable operators (e.g., `:::` or `<<-`) and suggest an alternative: undesirable_operator_linter = lintr::undesirable_operator_linter(), From e6b0c4fb7e888f4769bc03f134c3e11af4374c40 Mon Sep 17 00:00:00 2001 From: DivyanshuVorrtex Date: Sat, 6 Dec 2025 17:21:55 +0000 Subject: [PATCH 2/3] =?UTF-8?q?feat(stats/mannwhitneyu):=20add=20Mann?= =?UTF-8?q?=E2=80=93Whitney=20U=20test=20package=20fix-1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 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: na - task: lint_repl_help status: na - task: lint_javascript_src status: na - task: lint_javascript_cli status: na - task: lint_javascript_examples status: na - task: lint_javascript_tests status: na - task: lint_javascript_benchmarks status: na - task: lint_python status: na - 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: na - task: lint_license_headers status: passed --- --- lib/node_modules/@stdlib/stats/mannwhitneyu/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/README.md b/lib/node_modules/@stdlib/stats/mannwhitneyu/README.md index 8ed8233f04a6..5eb3c70a20e5 100644 --- a/lib/node_modules/@stdlib/stats/mannwhitneyu/README.md +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/README.md @@ -80,7 +80,7 @@ var out = mannWhitneyU( [ 7, 8, 9 ], [ 1, 2, 3 ], { By default, a two-sided test is performed. To perform either of the one-sided tests, set the `alternative` option to `less` or `greater`. ```javascript -out = mannWhitneyU( [ 5, 6, 7, 8 ], [ 1, 2, 3, 4 ], { +var out = mannWhitneyU( [ 5, 6, 7, 8 ], [ 1, 2, 3, 4 ], { 'alternative': 'greater', 'alpha': 0.05 }); From c7ece8f310ffed4771cd03c82abcc1f15cdd1b5a Mon Sep 17 00:00:00 2001 From: DivyanshuVorrtex Date: Sat, 6 Dec 2025 17:57:08 +0000 Subject: [PATCH 3/3] =?UTF-8?q?feat(stats/mannwhitneyu):=20add=20Mann?= =?UTF-8?q?=E2=80=93Whitney=20U=20test=20package=20fix-2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mannwhitneyu/test/fixtures/r/runner.R | 235 ++++++++++-------- tools/lint/r/linter.R | 9 +- 2 files changed, 141 insertions(+), 103 deletions(-) diff --git a/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/runner.R b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/runner.R index 69cc8bb4bb5a..01350a5daf9f 100644 --- a/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/runner.R +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/runner.R @@ -16,114 +16,149 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Set the precision to 16 digits: -options( digits = 16L ); +# Ensure jsonlite is available (works on R 3.5.3): +if (!requireNamespace("jsonlite", quietly = TRUE)) { + install.packages("jsonlite", repos = "https://cloud.r-project.org", quiet = TRUE) + if (!requireNamespace("jsonlite", quietly = TRUE)) { + message("jsonlite unavailable; cannot generate fixtures.") + quit(status = 0) + } +} + +# Set numeric precision: +options(digits = 16L) -#' Generate test fixtures. -#' -#' @examples -#' main(); main <- function() { - #' Get the script filepath. - #' - #' @return The absolute path of this script - #' - #' @examples - #' filepath <- get_script_path(); + get_script_path <- function() { - args <- commandArgs( trailingOnly = FALSE ); - needle <- '--file='; - match <- grep( needle, args ); - if ( length( match ) > 0L ) { - # Rscript: - filepath <- sub( needle, '', args[match] ); - } else { - ls_vars <- ls( sys.frames()[[1L]] ) - if ( 'fileName' %in% ls_vars ) { - # Source'd via RStudio: - filepath <- sys.frames()[[1L]]$fileName; # nolint - } else { - # Source'd via R console: - filepath <- sys.frames()[[1L]]$ofile; - } - } - return( normalizePath( filepath ) ); + args <- commandArgs(trailingOnly = FALSE) + needle <- "--file=" + match <- grep(needle, args) + if (length(match) > 0L) { + filepath <- sub(needle, "", args[match]) + } else { + ls_vars <- ls(sys.frames()[[1L]]) + if ("fileName" %in% ls_vars) { + filepath <- sys.frames()[[1L]]$fileName # nolint + } else { + filepath <- sys.frames()[[1L]]$ofile } - - #' Convert a data structure to JSON. - #' - #' @param x A data structure to convert - #' @return JSON blob - #' - #' @examples - #' x <- seq( -6.5, 25, 0.5 ); - #' json <- to_json( x ); - to_json <- function( x ) { - return( jsonlite::toJSON( x, digits = 16L, auto_unbox = TRUE ) ); } - - #' Generate an output absolute filepath based on the script directory. - #' - #' @param name An output filename - #' @return An absolute filepath - #' - #' @examples - #' filepath <- get_filepath( 'data.json' ); - get_filepath <- function( name ) { - return( paste( source_dir, '/', name, sep = '' ) ); + normalizePath(filepath) } - # Get the directory of this script: - source_dir <- dirname( get_script_path() ); - - # Generate test fixture data: - # Note: We set exact=FALSE to force normal approximation matching JS implementation. - high_p_res <- wilcox.test( c( 10.0, 11.0, 12.0, 13.0, 14.0 ), c( 1.0, 2.0, 3.0, 4.0, 5.0 ), alternative = 'two.sided', correct = FALSE, exact = FALSE ); - u_high <- min( high_p_res$statistic, ( 5.0 * 5.0 ) - high_p_res$statistic ); - high_p <- list( x = c( 10.0, 11.0, 12.0, 13.0, 14.0 ), y = c( 1.0, 2.0, 3.0, 4.0, 5.0 ), U = u_high, pValue = high_p_res$p.value, alternative = 'two-sided', alpha = 0.05, - rejected = high_p_res$p.value <= 0.05 ); - - medium_p_res <- wilcox.test( c( 5.0, 6.0, 7.0, 8.0 ), c( 4.0, 5.0, 6.0, 7.0 ), alternative = 'two.sided', correct = FALSE, exact = FALSE ); - u_med <- min( medium_p_res$statistic, ( 4.0 * 4.0 ) - medium_p_res$statistic ); - medium_p <- list( x = c( 5.0, 6.0, 7.0, 8.0 ), y = c( 4.0, 5.0, 6.0, 7.0 ), U = u_med, pValue = medium_p_res$p.value, alternative = 'two-sided', alpha = 0.05, - rejected = medium_p_res$p.value <= 0.05 ); - - low_p_res <- wilcox.test( c( 5.0, 6.0, 7.0, 8.0 ), c( 6.0, 7.0, 8.0, 9.0 ), alternative = 'two.sided', correct = FALSE, exact = FALSE ); - u_low <- min( low_p_res$statistic, ( 4.0 * 4.0 ) - low_p_res$statistic ); - low_p <- list( x = c( 5.0, 6.0, 7.0, 8.0 ), y = c( 6.0, 7.0, 8.0, 9.0 ), U = u_low, pValue = low_p_res$p.value, alternative = 'two-sided', alpha = 0.05, - rejected = low_p_res$p.value <= 0.05 ); - - less <- wilcox.test( c( 5.0, 6.0, 7.0, 8.0 ), c( 6.0, 7.0, 8.0, 9.0 ), alternative = 'less', correct = FALSE, exact = FALSE ); - less <- list( x = c( 5.0, 6.0, 7.0, 8.0 ), y = c( 6.0, 7.0, 8.0, 9.0 ), U = less$statistic, pValue = less$p.value, alternative = 'less', alpha = 0.05, - rejected = less$p.value <= 0.05 ); - - greater <- wilcox.test( c( 5.0, 6.0, 7.0, 8.0 ), c( 4.0, 5.0, 6.0, 7.0 ), alternative = 'greater', correct = FALSE, exact = FALSE ); - greater <- list( x = c( 5.0, 6.0, 7.0, 8.0 ), y = c( 4.0, 5.0, 6.0, 7.0 ), U = greater$statistic, pValue = greater$p.value, alternative = 'greater', alpha = 0.05, - rejected = greater$p.value <= 0.05 ); - - # Convert fixture data to JSON: - high_p <- to_json( high_p ); - medium_p <- to_json( medium_p ); - low_p <- to_json( low_p ); - less <- to_json( less ); - greater <- to_json( greater ); - - - # Write the data to file... - filepath <- get_filepath( 'high_p.json' ); - write( high_p, filepath ); - - filepath <- get_filepath( 'medium_p.json' ); - write( medium_p, filepath ); - - filepath <- get_filepath( 'low_p.json' ); - write( low_p, filepath ); + to_json <- function(x) { + jsonlite::toJSON(x, digits = 16L, auto_unbox = TRUE) + } - filepath <- get_filepath( 'less.json' ); - write( less, filepath ); + get_filepath <- function(name) { + paste(source_dir, "/", name, sep = "") + } - filepath <- get_filepath( 'greater.json' ); - write( greater, filepath ); + source_dir <- dirname(get_script_path()) + + # Generate test fixture data using base R wilcox.test: + high_p_res <- wilcox.test( + c(10, 11, 12, 13, 14), + c(1, 2, 3, 4, 5), + alternative = "two.sided", + correct = FALSE, + exact = FALSE + ) + u_high <- min(high_p_res$statistic, (5 * 5) - high_p_res$statistic) + high_p <- list( + x = c(10, 11, 12, 13, 14), + y = c(1, 2, 3, 4, 5), + U = u_high, + pValue = high_p_res$p.value, + alternative = "two-sided", + alpha = 0.05, + rejected = high_p_res$p.value <= 0.05 + ) + + medium_p_res <- wilcox.test( + c(5, 6, 7, 8), + c(4, 5, 6, 7), + alternative = "two.sided", + correct = FALSE, + exact = FALSE + ) + u_med <- min(medium_p_res$statistic, (4 * 4) - medium_p_res$statistic) + medium_p <- list( + x = c(5, 6, 7, 8), + y = c(4, 5, 6, 7), + U = u_med, + pValue = medium_p_res$p.value, + alternative = "two-sided", + alpha = 0.05, + rejected = medium_p_res$p.value <= 0.05 + ) + + low_p_res <- wilcox.test( + c(5, 6, 7, 8), + c(6, 7, 8, 9), + alternative = "two.sided", + correct = FALSE, + exact = FALSE + ) + u_low <- min(low_p_res$statistic, (4 * 4) - low_p_res$statistic) + low_p <- list( + x = c(5, 6, 7, 8), + y = c(6, 7, 8, 9), + U = u_low, + pValue = low_p_res$p.value, + alternative = "two-sided", + alpha = 0.05, + rejected = low_p_res$p.value <= 0.05 + ) + + less <- wilcox.test( + c(5, 6, 7, 8), + c(6, 7, 8, 9), + alternative = "less", + correct = FALSE, + exact = FALSE + ) + less <- list( + x = c(5, 6, 7, 8), + y = c(6, 7, 8, 9), + U = less$statistic, + pValue = less$p.value, + alternative = "less", + alpha = 0.05, + rejected = less$p.value <= 0.05 + ) + + greater <- wilcox.test( + c(5, 6, 7, 8), + c(4, 5, 6, 7), + alternative = "greater", + correct = FALSE, + exact = FALSE + ) + greater <- list( + x = c(5, 6, 7, 8), + y = c(4, 5, 6, 7), + U = greater$statistic, + pValue = greater$p.value, + alternative = "greater", + alpha = 0.05, + rejected = greater$p.value <= 0.05 + ) + + # Convert to JSON + high_p <- to_json(high_p) + medium_p <- to_json(medium_p) + low_p <- to_json(low_p) + less <- to_json(less) + greater <- to_json(greater) + + # Write fixtures + write(high_p, get_filepath("high_p.json")) + write(medium_p, get_filepath("medium_p.json")) + write(low_p, get_filepath("low_p.json")) + write(less, get_filepath("less.json")) + write(greater, get_filepath("greater.json")) } -main(); +main() diff --git a/tools/lint/r/linter.R b/tools/lint/r/linter.R index 435cf55fa9f9..db9905591700 100644 --- a/tools/lint/r/linter.R +++ b/tools/lint/r/linter.R @@ -25,7 +25,7 @@ # [1]: https://github.com/jimhester/lintr # Ensure that the `lintr` package is installed... -if ( !requireNamespace( 'lintr', quietly = TRUE ) ) { +if ( !require( 'lintr', quietly = TRUE, character.only = TRUE ) ) { install.packages( 'lintr', repos = 'http://lib.stat.cmu.edu/R/CRAN/', quiet = TRUE ); } @@ -39,7 +39,7 @@ if ( n == 0L ) { } # Specify which linters to use... -linters <- lintr::linters_with_defaults( defaults = lintr::default_linters, +linters <- lintr::linters_with_defaults( defaults = default_linters, # Check that no absolute paths are used: absolute_path_linter = lintr::absolute_path_linter(), @@ -52,6 +52,9 @@ linters <- lintr::linters_with_defaults( defaults = lintr::default_linters, # Allow commented code outside roxygen blocks: commented_code_linter = NULL, # lintr::commented_code_linter, + # Require the `[[` operator is used when extracting a single element from an object, not `[` (subsetting) or `$` (interactive use): + extraction_operator_linter = lintr::extraction_operator_linter(), + # Require that integers are explicitly typed using the form `1L` instead of `1`: implicit_integer_linter = lintr::implicit_integer_linter(), @@ -108,7 +111,7 @@ linters <- lintr::linters_with_defaults( defaults = lintr::default_linters, T_and_F_symbol_linter = lintr::T_and_F_symbol_linter(), # Report the use of undesirable functions (e.g., `attach` or `sapply`) and suggest an alternative: - undesirable_function_linter = lintr::undesirable_function_linter( fun = within( lintr::default_undesirable_functions, rm( options ) ) ), + undesirable_function_linter = lintr::undesirable_function_linter( fun = within( default_undesirable_functions, rm( options ) ) ), # Report the use of undesirable operators (e.g., `:::` or `<<-`) and suggest an alternative: undesirable_operator_linter = lintr::undesirable_operator_linter(),