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;
 | |
| };
 |