From 66b40cf34ebe01c358b4fd9a77266588b70b2e57 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Wed, 6 Dec 2023 14:24:39 +0100 Subject: [PATCH] fix: use unbiased standard deviation formula MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- src/utils/StatisticUtils.ts | 17 ++++++++++++++++- tests/utils/StatisticUtils.test.ts | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/utils/StatisticUtils.ts b/src/utils/StatisticUtils.ts index f0bd1f28..2ff71b0a 100644 --- a/src/utils/StatisticUtils.ts +++ b/src/utils/StatisticUtils.ts @@ -64,12 +64,27 @@ export const nthPercentile = (dataSet: number[], percentile: number): number => return sortedDataSet[percentileIndexInteger]; }; +/** + * 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, + (dataSet.length - 1), ); }; diff --git a/tests/utils/StatisticUtils.test.ts b/tests/utils/StatisticUtils.test.ts index d9aadf0c..38963dbe 100644 --- a/tests/utils/StatisticUtils.test.ts +++ b/tests/utils/StatisticUtils.test.ts @@ -33,6 +33,6 @@ await describe('StatisticUtils test suite', async () => { }); await it('Verify stdDeviation()', () => { - expect(stdDeviation([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(2.0256064851429216); + expect(stdDeviation([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(2.1879050645374383); }); }); -- 2.34.1