UNPKG

@jeremyqzt/nodestats

Version:

Helper methods for stats, combinatorics, permutations, probabilities and matricies

234 lines (211 loc) 8.56 kB
var zTable = require('./zTable'); /** Class aggregating statistical methods. */ class statsLib{ /** * Evaluates sum of an array. * @param {number[]} inArr - The array to sum * @return {number} Numerical value representing the sum of all array elements */ static sum(inArr){ let total = 0; for (let i = 0; i < inArr.length; i++){ total += inArr[i]; } return total; } /** * Evaluates geometric sum of an array. * @param {number[]} inArr - The array to sum * @return {number} Numerical value representing the geometric sum of all array elements */ static geometricSum(inArr){ if (inArr.length === 0){ return 0; } let total = inArr[0]; for (let i = 1; i < inArr.length; i++){ total *= inArr[i]; } return total; } /** * Evaluates statistical mean of an array. * @param {number[]} inArr - The array to find mean for. * @return {number} Numerical value representing the mean of all array elements */ static mean(inArr){ return statsLib.sum(inArr) / inArr.length; } /** * Evaluates statistical geometric mean of an array. * @param {number[]} inArr - The array to find geometric mean for. * @return {number} Numerical value representing the geometric mean of all array elements */ static geometricMean(inArr){ let totalGeometric = statsLib.geometricSum(inArr); return Math.pow(totalGeometric, 1/inArr.length); } /** * Evaluates statistical median of an array. * @param {number[]} inArr - The array to find median for. * @return {number} Numerical value representing the median of all array elements */ static median(inArr){ let newArr = [...inArr]; let arrSizeEven = newArr.length % 2 === 0; let midIdx = Math.floor(newArr.length / 2); newArr.sort(function(a, b) {return a - b;}); return arrSizeEven ? (newArr[midIdx] + newArr[midIdx - 1]) / 2 : newArr[midIdx]; } /** * Evaluates statistical mode of an array. * @param {number[]} inArr - The array to find mode for. * @return {number} Numerical value representing the mode of all array elements */ static mode(inArr){ let retMode = []; let modeDict = {}; let maxCount = 0; for (let i = 0; i < inArr.length; i++){ (inArr[i] in modeDict) ? modeDict[inArr[i]]++ : modeDict[inArr[i]] = 1; if (modeDict[inArr[i]] > maxCount){ retMode = [inArr[i]]; maxCount = modeDict[inArr[i]]; } else if (modeDict[inArr[i]] === maxCount){ retMode.push(inArr[i]); } } return retMode; } /** * Evaluates statistical standard deviation of an array. * @param {number[]} inArr - The array to find standard deviation for * @param {{population: boolean}} opt - Option denoting if a population or a sample is provided * @return {number} Numerical value representing the standard deviation of all array elements */ static stdev(inArr, opt = { "population": true, }){ let size = inArr.length; if (!opt["population"]){ size--; } let mean = statsLib.mean(inArr); let total = 0; for (let i = 0; i < inArr.length; i++){ total += Math.pow((inArr[i] - mean), 2); } return Math.sqrt(total / size); } /** * Finds an array element representing the given percentile. * @param {number} percentile - Percentile to find in the given array (0 <= percentile <= 100) * @param {number[]} inArr - Array to find the percentile element in * @return {!number} A numerical value that is a part of the input array representing the given percentile */ static absolutePercentile(percentile, inArr){ if (!inArr.length){ return undefined; } let newArr = [...inArr]; newArr.sort(function(a, b) {return a - b;}); let idxRank = Math.round((percentile / 100) * newArr.length) - 1; return newArr[idxRank]; } /** * Evaluates the Z score of a given value and a sample or population dataset array. * @param {number} val - Value to find Z score for * @param {number[]} inArr - The array representing the population or sample * @param {{population: boolean}} opt - Option denoting if a population or a sample is provided * @return {number} Numerical value representing the Z score the given value in the context of the dataset */ static zScore(val, inArr, opt = { "population": true, }){ let mean = statsLib.mean(inArr); let stdev = statsLib.stdev(inArr, opt); return (val - mean) / stdev; } /** * Evaluates the percentile of a given value and a sample or population dataset array. * @param {number} val - Value to find percentile for * @param {number[]} inArr - The array representing the population or sample * @param {{population: boolean}} opt - Option denoting if a population or a sample is provided * @return {number} Numerical value representing the percentile the given value in the context of the dataset */ static percentile(val, inArr, opt = { "population": true, }){ let z = statsLib.zScore(val, inArr, opt); return statsLib.zScorePercentile(z); } /** * Evaluates the percentile of a given value and a sample or population dataset array. * @param {number} val - Value to find percentile for * @param {number} mean - The value representing mean of the dataset * @param {number} stdev - The value representing standard deviation of the dataset * @return {number} Numerical value representing the percentile the given value in the context of the dataset */ static percentileFromMeanAndStdev(val, mean, stdev){ let diff = val - mean; let zScore = (diff/stdev); return statsLib.zScorePercentile(zScore); } /** * Evaluates the percentile of a given Z score, maximum is [-3.99, 3.99]. If the value is too large or too small, it goes to the nearest valid Z score. * @param {number} score - Z score to find percentile for * @return {number} Numerical value representing the percentile the given Z score */ static zScorePercentile(score){ if (!(typeof score == 'number')){ return undefined; } score = (score > 3.99) ? 3.99: score; score = (score < -3.99) ? -3.99: score; let combinedIdx = score.toFixed(2); let idx1 = combinedIdx.substr(0, combinedIdx.length - 1); let idx2 = combinedIdx.substr(combinedIdx.length - 1, 1); return zTable.zScoreTab[idx1][idx2]; } /** * Evaluates statistical correlation of two arrays. * @param {number[]} inArr1 - The first array to find correlation for * @param {number[]} inArr2 - The second array to find correlation for * @return {number} Numerical value representing the correlation of the 2 arrays */ static correlation(inArr1, inArr2){ if (inArr1.length !== inArr2.length){ return 0; } const arrSum = (x) => { let sum = 0; for (let i = 0; i < x.length; i++){ sum += x[i]; } return sum; } let n = inArr1.length; let inArr1Sum = arrSum(inArr1); let inArr2Sum = arrSum(inArr2); let inArr1Sq = arrSum(inArr1.map(function(num) { return Math.pow(num, 2) })); let inArr2Sq = arrSum(inArr2.map(function(num) { return Math.pow(num, 2) })); let xy = 0; for (let i = 0; i < n; i++){ xy += inArr1[i] * inArr2[i]; } let numo = (n*xy) - (inArr1Sum*inArr2Sum); let deno0 = (n*inArr1Sq) - Math.pow(inArr1Sum,2); let deno1 = (n*inArr2Sq) - Math.pow(inArr2Sum,2); let deno = Math.sqrt(deno0*deno1) let r = numo/deno; return r; } } module.exports = { statsLib: statsLib, };