diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..a4df25f
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "cSpell.words": ["Stdev"]
+}
diff --git a/lib/findPaths.js b/lib/findPaths.js
index 7f20757..947397f 100644
--- a/lib/findPaths.js
+++ b/lib/findPaths.js
@@ -5,6 +5,7 @@ import {
formatLargeOrSmall,
avg,
hackyGeomMean,
+ getCoefficientOfVariation,
} from "../lib/utils.js";
/* Functions */
@@ -301,6 +302,7 @@ export function CreateTable({ tableRows }) {
Possible relative values |
|
geomMean(relative values) |
+ Coefficient of variation |
@@ -317,6 +319,9 @@ export function CreateTable({ tableRows }) {
{formatLargeOrSmall(hackyGeomMean(row.distances))}
|
+
+ {formatLargeOrSmall(getCoefficientOfVariation(row.distances))}
+ |
))}
diff --git a/lib/utils.js b/lib/utils.js
index 5d48779..db131e8 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -117,3 +117,26 @@ export function conservativeNumMergeSortSteps(n) {
// export const geomMean = (arr) => arr.reduce((a, b) => a * b, 1); // ^ (1 / arr.length); // didn't work so well for low numbers.
export const increasingList = (n) => Array.from(Array(n).keys());
+
+function getStdev(arr) {
+ if (Array.isArray(arr) && arr.length > 0) {
+ const n = arr.length;
+ const mean = arr.reduce((a, b) => a + b) / n;
+ return Math.sqrt(
+ arr.map((x) => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n
+ );
+ } else {
+ return 0;
+ }
+}
+
+export const getCoefficientOfVariation = (arr) => {
+ let nonPositiveNumbers = arr.filter((x) => x <= 0);
+ if (nonPositiveNumbers.length == 0) {
+ let gm = geomMean(arr);
+ let stdev = getStdev(arr);
+ return stdev / gm;
+ } else {
+ return getStdev(arr) / avg(arr);
+ }
+};