simple-statistics
Version:
59 lines (53 loc) • 1.96 kB
JavaScript
/**
* The [Geometric Mean](https://en.wikipedia.org/wiki/Geometric_mean) is
* a mean function that is more useful for numbers in different
* ranges.
*
* This is the nth root of the input numbers multiplied by each other.
*
* The geometric mean is often useful for
* **[proportional growth](https://en.wikipedia.org/wiki/Geometric_mean#Proportional_growth)**: given
* growth rates for multiple years, like _80%, 16.66% and 42.85%_, a simple
* mean will incorrectly estimate an average growth rate, whereas a geometric
* mean will correctly estimate a growth rate that, over those years,
* will yield the same end value.
*
* This runs in `O(n)`, linear time, with respect to the length of the array.
*
* @param {Array<number>} x sample of one or more data points
* @returns {number} geometric mean
* @throws {Error} if x is empty
* @throws {Error} if x contains a negative number
* @example
* var growthRates = [1.80, 1.166666, 1.428571];
* var averageGrowth = ss.geometricMean(growthRates);
* var averageGrowthRates = [averageGrowth, averageGrowth, averageGrowth];
* var startingValue = 10;
* var startingValueMean = 10;
* growthRates.forEach(function(rate) {
* startingValue *= rate;
* });
* averageGrowthRates.forEach(function(rate) {
* startingValueMean *= rate;
* });
* startingValueMean === startingValue;
*/
function geometricMean(x) {
if (x.length === 0) {
throw new Error("geometricMean requires at least one data point");
}
// the starting value.
let value = 1;
for (let i = 0; i < x.length; i++) {
// the geometric mean is only valid for positive numbers
if (x[i] < 0) {
throw new Error(
"geometricMean requires only non-negative numbers as input"
);
}
// repeatedly multiply the value by each number
value *= x[i];
}
return Math.pow(value, 1 / x.length);
}
export default geometricMean;