75 lines
2.4 KiB
JavaScript
75 lines
2.4 KiB
JavaScript
|
// Helpers
|
||
|
const sum = (array) => array.reduce((a, b) => a + b, 0);
|
||
|
const probabilityToOdds = (p) => p / (1 - p);
|
||
|
const oddsToProbability = (o) => o / (1 + o);
|
||
|
const validateArray = (arr) =>
|
||
|
Array.isArray(arr) &&
|
||
|
arr.length > 0 &&
|
||
|
arr.reduce((a, b) => a && typeof b == "number" && b >= 0 && b <= 1, true);
|
||
|
|
||
|
// Main functions
|
||
|
export const median = (array) => {
|
||
|
if (!validateArray(array)) return -1;
|
||
|
// needs validation array not empty
|
||
|
let midway = Math.floor(array.length) / 2;
|
||
|
let arrayToBeSorted = [...array];
|
||
|
// sorting mutates the array, which I am averse to
|
||
|
let arraySorted = arrayToBeSorted.sort((a, b) => a - b);
|
||
|
if (midway % 2) {
|
||
|
return arraySorted[midway];
|
||
|
} else {
|
||
|
return (arraySorted[midway - 1] + arraySorted[midway]) / 2;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
export const arithmeticMean = (array) => {
|
||
|
if (!validateArray(array)) return -1;
|
||
|
let result = sum(array) / array.length;
|
||
|
return result;
|
||
|
};
|
||
|
|
||
|
export const geometricMean = (array) => {
|
||
|
if (!validateArray(array)) return -1;
|
||
|
// sum of logs seems more numerically stable than multiplying a lot of numbers 0<=p<=1
|
||
|
let arrayAsLog = array.map((p) => Math.log(p));
|
||
|
let sumOfLogs = sum(arrayAsLog) / arrayAsLog.length;
|
||
|
let result = Math.exp(sumOfLogs);
|
||
|
return result;
|
||
|
};
|
||
|
|
||
|
export const geometricMeanOfOdds = (array) => {
|
||
|
if (!validateArray(array)) return -1;
|
||
|
let arrayOfOdds = array.map((p) => probabilityToOdds(p));
|
||
|
let arrayOfLogsOfOdds = arrayOfOdds.map((p) => Math.log(p));
|
||
|
let sumOfLogsOfOdds = sum(arrayOfLogsOfOdds) / arrayOfLogsOfOdds.length;
|
||
|
let geomMeanOfOdds = Math.exp(sumOfLogsOfOdds);
|
||
|
let result = oddsToProbability(geomMeanOfOdds);
|
||
|
return result;
|
||
|
};
|
||
|
|
||
|
export const extremizedGeometricMeanOfOdds = (
|
||
|
array,
|
||
|
extremizationParameter = 1.5
|
||
|
) => {
|
||
|
if (!validateArray(array)) return -1;
|
||
|
let arrayOfOdds = array.map((p) => probabilityToOdds(p));
|
||
|
let arrayOfLogsOfOdds = arrayOfOdds.map((p) => Math.log(p));
|
||
|
let extremizedSumOfLogsOfOdds =
|
||
|
(extremizationParameter * sum(arrayOfLogsOfOdds)) /
|
||
|
arrayOfLogsOfOdds.length;
|
||
|
let extremizedGeomMeanOfOdds = Math.exp(extremizedSumOfLogsOfOdds);
|
||
|
let result = oddsToProbability(extremizedGeomMeanOfOdds);
|
||
|
return result;
|
||
|
};
|
||
|
|
||
|
export const neyman = (array) => {
|
||
|
if (!validateArray(array)) return -1;
|
||
|
let n = array.length;
|
||
|
|
||
|
let d =
|
||
|
(n * (Math.sqrt(3 * Math.pow(n, 2) - 3 * n + 1) - 2)) /
|
||
|
(Math.pow(n, 2) - n - 1);
|
||
|
let result = extremizedGeometricMeanOfOdds(array, d);
|
||
|
return result;
|
||
|
};
|