main.js (5282B)
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 isNumberArray = require( '@stdlib/assert/is-number-array' ).primitives; 24 var isTypedArrayLike = require( '@stdlib/assert/is-typed-array-like' ); 25 var isPositiveNumber = require( '@stdlib/assert/is-positive-number' ).isPrimitive; 26 var setReadOnly = require( '@stdlib/utils/define-read-only-property' ); 27 var quantileFactory = require( './../../base/dists/normal/quantile' ).factory; 28 var cdfFactory = require( './../../base/dists/normal/cdf' ).factory; 29 var sqrt = require( '@stdlib/math/base/special/sqrt' ); 30 var abs = require( '@stdlib/math/base/special/abs' ); 31 var mean = require( './../../base/mean' ); 32 var NINF = require( '@stdlib/constants/float64/ninf' ); 33 var PINF = require( '@stdlib/constants/float64/pinf' ); 34 var validate = require( './validate.js' ); 35 var print = require( './print.js' ); // eslint-disable-line stdlib/no-redeclare 36 37 38 // VARIABLES // 39 40 var normQuantile = quantileFactory( 0.0, 1.0 ); 41 var normCDF = cdfFactory( 0.0, 1.0 ); 42 43 44 // MAIN // 45 46 /** 47 * Computes a two-sample z-test. 48 * 49 * @param {NumericArray} x - first data array 50 * @param {NumericArray} y - second data array 51 * @param {PositiveNumber} sigmax - known standard deviation of first group 52 * @param {PositiveNumber} sigmay - known standard deviation of second group 53 * @param {Options} [options] - function options 54 * @param {number} [options.alpha=0.05] - significance level 55 * @param {string} [options.alternative='two-sided'] - alternative hypothesis (`two-sided`, `less` or `greater`) 56 * @param {number} [options.difference=0] - difference in means under H0 57 * @throws {TypeError} x argument has to be a typed array or array of numbers 58 * @throws {TypeError} y argument has to be a typed array or array of numbers 59 * @throws {TypeError} sigmax argument has to be a positive number 60 * @throws {TypeError} sigmay argument has to be a positive number 61 * @throws {TypeError} options has to be simple object 62 * @throws {TypeError} must provide valid options 63 * @throws {Error} `alternative` option must be either `two-sided`, `less`, or `greater` 64 * @returns {Object} test result object 65 */ 66 function ztest2( x, y, sigmax, sigmay, options ) { 67 var stderr; 68 var alpha; 69 var xmean; 70 var ymean; 71 var cint; 72 var diff; 73 var opts; 74 var pval; 75 var xvar; 76 var yvar; 77 var stat; 78 var alt; 79 var err; 80 var out; 81 var nx; 82 var ny; 83 84 if ( !isTypedArrayLike( x ) && !isNumberArray( x ) ) { 85 throw new TypeError( 'invalid argument. First argument `x` must be a numeric array. Value: `' + x + '`.' ); 86 } 87 if ( !isTypedArrayLike( y ) && !isNumberArray( y ) ) { 88 throw new TypeError( 'invalid argument. Second argument `y` must be a numeric array. Value: `' + y + '`.' ); 89 } 90 if ( !isPositiveNumber( sigmax ) ) { 91 throw new TypeError( 'invalid argument. Third argument `sigmax` must be a positive number. Value: `' + sigmax + '`.' ); 92 } 93 if ( !isPositiveNumber( sigmay ) ) { 94 throw new TypeError( 'invalid argument. Third argument `sigmay` must be a positive number. Value: `' + sigmay + '`.' ); 95 } 96 opts = {}; 97 if ( options ) { 98 err = validate( opts, options ); 99 if ( err ) { 100 throw err; 101 } 102 } 103 diff = opts.difference || 0.0; 104 if ( opts.alpha === void 0 ) { 105 alpha = 0.05; 106 } else { 107 alpha = opts.alpha; 108 } 109 nx = x.length; 110 ny = y.length; 111 112 xvar = sigmax * sigmax; 113 yvar = sigmay * sigmay; 114 stderr = sqrt( (xvar/nx) + (yvar/ny) ); 115 116 xmean = mean( nx, x, 1 ); 117 ymean = mean( ny, y, 1 ); 118 stat = ( xmean - ymean - diff ) / stderr; 119 120 alt = opts.alternative || 'two-sided'; 121 switch ( alt ) { 122 case 'two-sided': 123 pval = 2.0 * normCDF( -abs(stat) ); 124 cint = [ 125 stat - normQuantile( 1.0-(alpha/2.0) ), 126 stat + normQuantile( 1.0-(alpha/2.0) ) 127 ]; 128 cint[ 0 ] = diff + (cint[ 0 ] * stderr); 129 cint[ 1 ] = diff + (cint[ 1 ] * stderr); 130 break; 131 case 'greater': 132 pval = 1.0 - normCDF( stat ); 133 cint = [ stat - normQuantile( 1.0-alpha ), PINF ]; 134 cint[ 0 ] = diff + (cint[ 0 ] * stderr); 135 break; 136 case 'less': 137 pval = normCDF( stat ); 138 cint = [ NINF, stat + normQuantile( 1.0-alpha ) ]; 139 cint[ 1 ] = diff + (cint[ 1 ] * stderr); 140 break; 141 default: 142 throw new Error( 'Invalid option. `alternative` must be either `two-sided`, `less` or `greater`. Value: `' + alt + '`' ); 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, 'ci', cint ); 150 setReadOnly( out, 'alternative', alt ); 151 setReadOnly( out, 'method', 'Two-sample z-test' ); 152 setReadOnly( out, 'nullValue', diff ); 153 setReadOnly( out, 'xmean', xmean ); 154 setReadOnly( out, 'ymean', ymean ); 155 setReadOnly( out, 'print', print ); 156 return out; 157 } 158 159 160 // EXPORTS // 161 162 module.exports = ztest2;