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..5eb3c70a20e5 --- /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 +var 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..01350a5daf9f --- /dev/null +++ b/lib/node_modules/@stdlib/stats/mannwhitneyu/test/fixtures/r/runner.R @@ -0,0 +1,164 @@ +#!/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. + +# 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) + +main <- function() { + + get_script_path <- function() { + 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 + } + } + normalizePath(filepath) + } + + to_json <- function(x) { + jsonlite::toJSON(x, digits = 16L, auto_unbox = TRUE) + } + + get_filepath <- function(name) { + paste(source_dir, "/", name, sep = "") + } + + 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() 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(); +});