build(deps-dev): apply updates
[e-mobility-charging-stations-simulator.git] / src / utils / StatisticUtils.ts
index a2d906eb06c5e06af6b44ac9b8fb607b13a7b69c..2ff71b0acb2ffa897a5d07f0e7bcd18719314903 100644 (file)
@@ -1,5 +1,29 @@
 import { isEmptyArray, isNullOrUndefined } from './Utils';
 
+/**
+ * Computes the average of the given data set.
+ *
+ * @param dataSet - Data set.
+ * @returns The average of the given data set.
+ * @internal
+ */
+export const average = (dataSet: number[]): number => {
+  if (Array.isArray(dataSet) && dataSet.length === 0) {
+    return 0;
+  }
+  if (Array.isArray(dataSet) && dataSet.length === 1) {
+    return dataSet[0];
+  }
+  return dataSet.reduce((accumulator, nb) => accumulator + nb, 0) / dataSet.length;
+};
+
+/**
+ * Computes the median of the given data set.
+ *
+ * @param dataSet - Data set.
+ * @returns The median of the given data set.
+ * @internal
+ */
 export const median = (dataSet: number[]): number => {
   if (isEmptyArray(dataSet)) {
     return 0;
@@ -40,16 +64,27 @@ export const nthPercentile = (dataSet: number[], percentile: number): number =>
   return sortedDataSet[percentileIndexInteger];
 };
 
-export const stdDeviation = (dataSet: number[]): number => {
-  let totalDataSet = 0;
-  for (const data of dataSet) {
-    totalDataSet += data;
-  }
-  const dataSetMean = totalDataSet / dataSet.length;
-  let totalGeometricDeviation = 0;
-  for (const data of dataSet) {
-    const deviation = data - dataSetMean;
-    totalGeometricDeviation += deviation * deviation;
-  }
-  return Math.sqrt(totalGeometricDeviation / dataSet.length);
+/**
+ * Computes the sample standard deviation of the given data set.
+ *
+ * @param dataSet - Data set.
+ * @param dataSetAverage - Average of the data set.
+ * @returns The sample standard deviation of the given data set.
+ * @see https://en.wikipedia.org/wiki/Unbiased_estimation_of_standard_deviation
+ * @internal
+ */
+export const stdDeviation = (
+  dataSet: number[],
+  dataSetAverage: number = average(dataSet),
+): number => {
+  if (isEmptyArray(dataSet)) {
+    return 0;
+  }
+  if (Array.isArray(dataSet) && dataSet.length === 1) {
+    return 0;
+  }
+  return Math.sqrt(
+    dataSet.reduce((accumulator, num) => accumulator + Math.pow(num - dataSetAverage, 2), 0) /
+      (dataSet.length - 1),
+  );
 };