UNPKG

compute-quantile

Version:

Computes a quantile for a numeric array.

125 lines (108 loc) 2.8 kB
/** * * COMPUTE: quantile * * * DESCRIPTION: * - Computes a quantile for a numeric array. * * * NOTES: * [1] * * * TODO: * [1] * * * LICENSE: * MIT * * Copyright (c) 2014. Athan Reines. * * * AUTHOR: * Athan Reines. kgryte@gmail.com. 2014. * */ 'use strict'; // MODULES // var isObject = require( 'validate.io-object' ); // FUNCTIONS // /** * FUNCTION: ascending( a, b ) * Comparator function used to sort values in ascending order. * * @private * @param {Number} a * @param {Number} b * @returns {Number} difference between `a` and `b` */ function ascending( a, b ) { return a - b; } // end FUNCTION ascending() // QUANTILE // /** * FUNCTION: quantile( arr, prob[, opts] ) * Computes a quantile for a numeric array. * * @private * @param {Array} arr - 1d array * @param {Number} prob - quantile prob [0,1] * @param {Object} [opts] - method options: `method`: method used to interpolate a quantile value `sorted`: boolean flag indicating if the input array is sorted * @returns {Number} quantile value */ function quantile( arr, p, opts ) { if ( !Array.isArray( arr ) ) { throw new TypeError( 'quantile()::invalid input argument. First argument must be an array.' ); } if ( typeof p !== 'number' || p !== p ) { throw new TypeError( 'quantile()::invalid input argument. Quantile probability must be numeric.' ); } if ( p < 0 || p > 1 ) { throw new TypeError( 'quantile()::invalid input argument. Quantile probability must be on the interval [0,1].' ); } if ( arguments.length > 2 ) { if ( !isObject( opts ) ) { throw new TypeError( 'quantile()::invalid input argument. Options must be an object.' ); } if ( opts.hasOwnProperty( 'sorted' ) && typeof opts.sorted !== 'boolean' ) { throw new TypeError( 'quantile()::invalid input argument. Sorted flag must be a boolean.' ); } if ( opts.hasOwnProperty( 'method' ) && typeof opts.method !== 'string' ) { throw new TypeError( 'quantile()::invalid input argument. Method must be a string.' ); } // TODO: validate that the requested method is supported. list.indexOf( method ) } else { opts = {}; } var len = arr.length, id; if ( !opts.sorted ) { arr = arr.slice(); arr.sort( ascending ); } // Cases... // [0] 0th percentile is the minimum value... if ( p === 0.0 ) { return arr[ 0 ]; } // [1] 100th percentile is the maximum value... if ( p === 1.0 ) { return arr[ len-1 ]; } // Calculate the vector index marking the quantile: id = ( len*p ) - 1; // [2] Is the index an integer? if ( id === Math.floor( id ) ) { // Value is the average between the value at id and id+1: return ( arr[ id ] + arr[ id+1 ] ) / 2.0; } // [3] Round up to the next index: id = Math.ceil( id ); return arr[ id ]; } // end FUNCTION quantile() // EXPORTS // module.exports = quantile;