Skip to content

Instantly share code, notes, and snippets.

@nathansmith
Last active July 2, 2024 17:16
Show Gist options
  • Save nathansmith/a291647a8b597a88ed07c81fe69231a1 to your computer and use it in GitHub Desktop.
Save nathansmith/a291647a8b597a88ed07c81fe69231a1 to your computer and use it in GitHub Desktop.
Parses a numeric list into: mean, median, mode, etc.
/**
* Gets the median for a list of numbers.
*
* @param {number[]} [listSorted=[]]
* @returns {number}
*/
const getMedian = (listSorted = []) => {
// Get count.
const listCount = listSorted.length;
// Get middle index.
const indexMiddle = Math.floor(listCount / 2);
// Get median.
let median = listSorted[indexMiddle];
// Even count: YES.
if (listCount % 2 === 0) {
// Update median.
median = (listSorted[indexMiddle - 1] + listSorted[indexMiddle]) / 2;
}
// Expose number.
return median;
};
/**
* Rounds to two decimal places.
*
* @param {number} [n=0]
* @returns {number}
*/
const roundTwoDecimals = (n = 0) => {
// Expose number.
return Math.round(n * 100) / 100;
};
/**
* Parses a list of numbers and computes:
*
* - Mean = Average value.
* - Median = Middle value.
* - Mode = Most frequent value(s).
* - Maximum = Highest value.
* - Minimum = Lowest value.
* - Range = Diff between maximum and minimum.
* - Range interquartile = Diff between Q3 and Q1.
* - Standard deviation = Square root of variance.
* - Variance = Squared deviation from the mean.
*
* @param {number[]} [list=[]]
* @returns {object} obj
* @returns {number} obj.maximum
* @returns {number} obj.mean
* @returns {number} obj.median
* @returns {number} obj.minimum
* @returns {number[]} obj.mode
* @returns {number} obj.standardDeviation
* @returns {number} obj.range
* @returns {number} obj.rangeInterquartile
* @returns {number} obj.variance
*/
const getListStats = (list = []) => {
// Get count.
const listCount = list.length;
// Get sorted list.
const listSorted = list.slice().sort((a, b) => a - b);
// Get min, max, range.
const minimum = listSorted.at(0);
const maximum = listSorted.at(-1);
const range = maximum - minimum;
// Set later.
const modeObj = {};
let total = 0;
let totalSquares = 0;
// Loop through.
for (const value of listSorted) {
// Increment count.
modeObj[value] ||= 0;
modeObj[value]++;
// Increment total.
total += value;
totalSquares += Math.pow(value, 2);
}
// Get mean, median.
const mean = total / listCount;
const median = getMedian(listSorted);
// Get mode.
const modeEntries = Object.entries(modeObj).sort((a, b) => b[1] - a[1]);
const modeMax = modeEntries[0]?.[1];
const mode = [];
// Loop through.
for (const [key, value] of modeEntries) {
// Equal to max: YES.
if (value === modeMax) {
// Add to mode.
mode.push(parseFloat(key));
}
}
// Get quartiles.
const quartile1 = getMedian(listSorted.slice(0, Math.floor(listCount / 2)));
const quartile3 = getMedian(listSorted.slice(Math.ceil(listCount / 2)));
const rangeInterquartile = quartile3 - quartile1;
// Get variance & deviation.
const variance = (totalSquares / listCount) - Math.pow(mean, 2);
const standardDeviation = Math.sqrt(variance);
// Expose object.
return {
mean: roundTwoDecimals(mean || 0),
median: roundTwoDecimals(median || 0),
mode: mode.length ? mode.map(roundTwoDecimals) : [0],
maximum: roundTwoDecimals(maximum || 0),
minimum: roundTwoDecimals(minimum || 0),
range: roundTwoDecimals(range || 0),
rangeInterquartile: roundTwoDecimals(rangeInterquartile || 0),
standardDeviation: roundTwoDecimals(standardDeviation || 0),
variance: roundTwoDecimals(variance || 0),
};
};
/*
=====
NOTE:
=====
To call this function, pass an array of values like so.
You can then use the resulting object however you need.
```
// Get list.
const listOfNumbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2];
// Get stats.
const listStats = getListStats(listOfNumbers);
// Peel apart.
const {
mean,
median,
mode,
maximum,
minimum,
range,
rangeInterquartile,
standardDeviation,
variance,
} = listStats;
```
*/
// Lists of numbers.
const list1 = [3, 7, 5, 4, 5, 6, 7, 8, 6, 5];
const list2 = [34, 54, 17, 26, 34, 25, 14, 24, 25, 23];
const list3 = [154, 167, 132, 145, 154, 145, 113, 156, 154, 123];
const list4 = [];
// Log results.
console.clear();
console.log("===>>> list1", JSON.stringify(getListStats(list1), null, 2));
console.log("===>>> list2", JSON.stringify(getListStats(list2), null, 2));
console.log("===>>> list3", JSON.stringify(getListStats(list3), null, 2));
console.log("===>>> list4", JSON.stringify(getListStats(list4), null, 2));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment