main.js (4524B)
1 /** 2 * @license Apache-2.0 3 * 4 * Copyright (c) 2018 The Stdlib Authors. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 'use strict'; 20 21 // MODULES // 22 23 var isCollection = require( '@stdlib/assert/is-collection' ); 24 var isPlainObject = require( '@stdlib/assert/is-plain-object' ); 25 var setReadOnly = require( '@stdlib/utils/define-read-only-property' ); 26 var objectKeys = require( '@stdlib/utils/keys' ); 27 var chisqCDF = require( './../../base/dists/chisquare/cdf' ); 28 var group = require( '@stdlib/utils/group' ); 29 var ln = require( '@stdlib/math/base/special/ln' ); 30 var variance = require( './variance.js' ); 31 var validate = require( './validate.js' ); 32 var print = require( './print.js' ); // eslint-disable-line stdlib/no-redeclare 33 34 35 // MAIN // 36 37 /** 38 * Computes Bartlett’s test for equal variances. 39 * 40 * @param {...NumericArray} arguments - either two or more number arrays or a single numeric array if an array of group indicators is supplied as an option 41 * @param {Options} [options] - function options 42 * @param {number} [options.alpha=0.05] - significance level 43 * @param {Array} [options.groups] - array of group indicators 44 * @throws {TypeError} must provide array-like arguments 45 * @throws {RangeError} alpha option has to be a number in the interval `[0,1]` 46 * @throws {Error} must provide at least two array-like arguments if `groups` is not set 47 * @throws {TypeError} options has to be simple object 48 * @throws {TypeError} must provide valid options 49 * @returns {Object} test results 50 * 51 * @example 52 * // Data from Hollander & Wolfe (1973), p. 116: 53 * var x = [ 2.9, 3.0, 2.5, 2.6, 3.2 ]; 54 * var y = [ 3.8, 2.7, 4.0, 2.4 ]; 55 * var z = [ 2.8, 3.4, 3.7, 2.2, 2.0 ]; 56 * 57 * var out = bartlett( x, y, z ); 58 * // returns {...} 59 */ 60 function bartlett() { 61 var options; 62 var ngroups; 63 var ninvSum; 64 var levels; 65 var table; 66 var alpha; 67 var nSum; 68 var vSum; 69 var args; 70 var opts; 71 var pval; 72 var stat; 73 var arg; 74 var err; 75 var lnv; 76 var out; 77 var df; 78 var n; 79 var v; 80 var i; 81 82 args = []; 83 ngroups = arguments.length; 84 opts = {}; 85 if ( isPlainObject( arguments[ ngroups - 1 ] ) ) { 86 options = arguments[ ngroups - 1 ]; 87 ngroups -= 1; 88 err = validate( opts, options ); 89 if ( err ) { 90 throw err; 91 } 92 } 93 if ( opts.groups ) { 94 table = group( arguments[ 0 ], opts.groups ); 95 levels = objectKeys( table ); 96 ngroups = levels.length; 97 if ( ngroups < 2 ) { 98 throw new Error( 'invalid number of groups. `groups` array must contain at least two unique elements. Value: `' + levels + '`.' ); 99 } 100 for ( i = 0; i < ngroups; i++ ) { 101 args.push( table[ levels[ i ] ] ); 102 } 103 } else { 104 for ( i = 0; i < ngroups; i++ ) { 105 args.push( arguments[ i ] ); 106 } 107 } 108 nSum = 0; 109 ninvSum = 0.0; 110 vSum = 0.0; 111 lnv = 0.0; 112 n = new Array( ngroups ); 113 v = n.slice(); 114 for ( i = 0; i < ngroups; i++ ) { 115 arg = args[ i ]; 116 if ( !isCollection( arg ) ) { 117 throw new TypeError( 'invalid argument. Must provide array-like arguments. Value: `' + arg + '`.' ); 118 } 119 if ( arg.length === 0 ) { 120 throw new Error( 'invalid argument. Supplied arrays cannot be empty. Value: `' + arg + '`.' ); 121 } 122 n[ i ] = arg.length - 1; 123 nSum += n[ i ]; 124 ninvSum += 1.0 / n[ i ]; 125 v[ i ] = variance( arg ); 126 vSum += ( n[ i ] * v[ i ] ); 127 lnv += n[ i ] * ln( v[ i ] ); 128 } 129 vSum /= nSum; 130 if ( opts.alpha === void 0 ) { 131 alpha = 0.05; 132 } else { 133 alpha = opts.alpha; 134 } 135 if ( alpha < 0.0 || alpha > 1.0 ) { 136 throw new RangeError( 'invalid argument. Option `alpha` must be a number in the range 0 to 1. Value: `' + alpha + '`.' ); 137 } 138 139 stat = ( ( nSum * ln( vSum ) ) - lnv ); 140 stat /= ( 1.0 + ( ( ninvSum - ( 1.0 / nSum ) ) / ( 3 * ( ngroups-1 ) ) ) ); 141 df = ngroups - 1; 142 pval = 1.0 - chisqCDF( stat, df ); 143 144 out = {}; 145 setReadOnly( out, 'rejected', pval <= alpha ); 146 setReadOnly( out, 'alpha', alpha ); 147 setReadOnly( out, 'pValue', pval ); 148 setReadOnly( out, 'statistic', stat ); 149 setReadOnly( out, 'df', df ); 150 setReadOnly( out, 'method', 'Bartlett\'s test of equal variances' ); 151 setReadOnly( out, 'print', print ); 152 return out; 153 } 154 155 156 // EXPORTS // 157 158 module.exports = bartlett;