results.js (6713B)
1 /** 2 * @license Apache-2.0 3 * 4 * Copyright (c) 2020 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 /* eslint-disable no-invalid-this, no-restricted-syntax */ 20 21 'use strict'; 22 23 // MODULES // 24 25 var isPositiveInteger = require( '@stdlib/assert/is-positive-integer' ); 26 var isObject = require( '@stdlib/assert/is-plain-object' ); 27 var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive; 28 var hasOwnProp = require( '@stdlib/assert/has-own-property' ); 29 var roundn = require( '@stdlib/math/base/special/roundn' ); 30 var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' ); 31 var setReadOnlyAccessor = require( '@stdlib/utils/define-nonenumerable-read-only-accessor' ); 32 33 34 // MAIN // 35 36 /** 37 * Returns a results object. 38 * 39 * @private 40 * @constructor 41 * @param {number} pValue - p-value 42 * @param {number} alpha - significance 43 * @param {number} statistic - test statistic 44 * @param {(number|null)} df - degrees of freedom 45 * @returns {Results} results object 46 * 47 * @example 48 * var res = new Results( 0.0406, 0.05, 9.9901, 4 ); 49 * // returns <Results> 50 */ 51 function Results( pValue, alpha, statistic, df ) { 52 if ( !(this instanceof Results) ) { 53 return new Results( pValue, alpha, statistic, df ); 54 } 55 this._pValue = pValue; 56 this._alpha = alpha; 57 this._statistic = statistic; 58 this._df = df; 59 return this; 60 } 61 62 /** 63 * Significance level. 64 * 65 * @private 66 * @name alpha 67 * @memberof Results.prototype 68 * @type {number} 69 * 70 * @example 71 * var res = new Results( 0.0406, 0.05, 9.9901, 4 ); 72 * 73 * var alpha = res.alpha; 74 * // returns 0.05 75 */ 76 setReadOnlyAccessor( Results.prototype, 'alpha', function get() { 77 return this._alpha; 78 }); 79 80 /** 81 * Degrees of freedom. 82 * 83 * @private 84 * @name df 85 * @memberof Results.prototype 86 * @type {(number|null)} 87 * 88 * @example 89 * var res = new Results( 0.0406, 0.05, 9.9901, 4 ); 90 * 91 * var df = res.df; 92 * // returns 4 93 */ 94 setReadOnlyAccessor( Results.prototype, 'df', function get() { 95 return this._df; 96 }); 97 98 /** 99 * Test name. 100 * 101 * @private 102 * @name method 103 * @memberof Results.prototype 104 * @type {string} 105 * 106 * @example 107 * var res = new Results( 0.0406, 0.05, 9.9901, 4 ); 108 * 109 * var method = res.method; 110 * // returns 'Chi-square goodness-of-fit test' 111 */ 112 setReadOnly( Results.prototype, 'method', 'Chi-square goodness-of-fit test' ); 113 114 /** 115 * Test p-value. 116 * 117 * @private 118 * @name pValue 119 * @memberof Results.prototype 120 * @type {number} 121 * 122 * @example 123 * var res = new Results( 0.0406, 0.05, 9.9901, 4 ); 124 * 125 * var pval = res.pValue; 126 * // returns 0.0406 127 */ 128 setReadOnlyAccessor( Results.prototype, 'pValue', function get() { 129 return this._pValue; 130 }); 131 132 /** 133 * Boolean indicating the test decision. 134 * 135 * @private 136 * @name rejected 137 * @memberof Results.prototype 138 * @type {boolean} 139 * 140 * @example 141 * var res = new Results( 0.0406, 0.05, 9.9901, 4 ); 142 * 143 * var bool = res.rejected; 144 * // returns true 145 */ 146 setReadOnlyAccessor( Results.prototype, 'rejected', function get() { 147 return ( this._pValue <= this._alpha ); 148 }); 149 150 /** 151 * Test statistic. 152 * 153 * @private 154 * @name statistic 155 * @memberof Results.prototype 156 * @type {number} 157 * 158 * @example 159 * var res = new Results( 0.0406, 0.05, 9.9901, 4 ); 160 * 161 * var stat = res.statistic; 162 * // returns 9.9901 163 */ 164 setReadOnlyAccessor( Results.prototype, 'statistic', function get() { 165 return this._statistic; 166 }); 167 168 /** 169 * Serializes a results object as a string. 170 * 171 * ## Notes 172 * 173 * - Example output: 174 * 175 * ```text 176 * 177 * Chi-square goodness-of-fit test 178 * 179 * Null hypothesis: population probabilities are equal to those in p 180 * 181 * pValue: 0.0406 182 * statistic: 9.9901 183 * degrees of freedom: 4 184 * 185 * Test Decision: Reject null in favor of alternative at 5% significance level 186 * 187 * ``` 188 * 189 * @private 190 * @name toString 191 * @memberof Results.prototype 192 * @type {Function} 193 * @param {Options} [opts] - options object 194 * @param {PositiveInteger} [opts.digits=4] - number of digits after the decimal point 195 * @param {boolean} [opts.decision=true] - boolean indicating whether to show the test decision 196 * @throws {TypeError} options argument must be an object 197 * @throws {TypeError} must provide valid options 198 * @returns {string} serialized results 199 * 200 * @example 201 * var res = new Results( 0.0406, 0.05, 9.9901, 4 ); 202 * 203 * var str = res.toString(); 204 * // returns <string> 205 */ 206 setReadOnly( Results.prototype, 'toString', function toString( opts ) { 207 var decision; 208 var dgts; 209 var out; 210 211 dgts = 4; 212 decision = true; 213 if ( arguments.length > 0 ) { 214 if ( !isObject( opts ) ) { 215 throw new TypeError( 'invalid argument. Must provide an object. Value: `' + opts + '`.' ); 216 } 217 if ( hasOwnProp( opts, 'digits' ) ) { 218 if ( !isPositiveInteger( opts.digits ) ) { 219 throw new TypeError( 'invalid option. `digits` option must be a positive integer. Option: `' + opts.digits + '`.' ); 220 } 221 dgts = opts.digits; 222 } 223 if ( hasOwnProp( opts, 'decision' ) ) { 224 if ( !isBoolean( opts.decision ) ) { 225 throw new TypeError( 'invalid option. `decision` option must be a boolean primitive. Option: `' + opts.decision + '`.' ); 226 } 227 decision = opts.decision; 228 } 229 } 230 out = [ 231 this.method, 232 '', 233 '', 234 'Null hypothesis: population probabilities are equal to those in p', 235 '', 236 '', 237 ' pValue: ' + roundn( this._pValue, -dgts ), 238 ' statistic: ' + roundn( this._statistic, -dgts ), 239 ' degrees of freedom: ' + this._df, 240 '' 241 ]; 242 if ( decision ) { 243 out.push( 'Test Decision: ' + ( ( this.rejected ) ? 'Reject' : 'Fail to reject' ) + ' null in favor of alternative at ' + (this._alpha*100.0) + '% significance level' ); 244 out.push( '' ); 245 } 246 return out.join( '\n' ); 247 }); 248 249 /** 250 * Serializes a results object as a JSON object. 251 * 252 * ## Notes 253 * 254 * - `JSON.stringify()` implicitly calls this method when stringifying a `Results` instance. 255 * 256 * @private 257 * @name toJSON 258 * @memberof Results.prototype 259 * @type {Function} 260 * @returns {Object} serialized object 261 * 262 * @example 263 * var res = new Results( 0.0406, 0.05, 9.9901, 4 ); 264 * 265 * var o = res.toJSON(); 266 * // returns {'rejected': true, 'alpha': 0.05, 'pValue': 0.0406, 'df': 4, ...} 267 */ 268 setReadOnly( Results.prototype, 'toJSON', function toJSON() { 269 return { 270 'rejected': this.rejected, 271 'alpha': this._alpha, 272 'pValue': this._pValue, 273 'df': this._df, 274 'statistic': this._statistic, 275 'method': this.method 276 }; 277 }); 278 279 280 // EXPORTS // 281 282 module.exports = Results;