diff --git a/packages/visx-stats/src/util/computeStats.ts b/packages/visx-stats/src/util/computeStats.ts index 397b01528..c188b3344 100644 --- a/packages/visx-stats/src/util/computeStats.ts +++ b/packages/visx-stats/src/util/computeStats.ts @@ -23,10 +23,14 @@ export default function computeStats(numericalArray: number[]) { const thirdQuartile = calcMedian(upperHalf); const IQR = thirdQuartile - firstQuartile; - const min = firstQuartile - 1.5 * IQR; - const max = thirdQuartile + 1.5 * IQR; + let min = firstQuartile - 1.5 * IQR; + let max = thirdQuartile + 1.5 * IQR; const outliers = points.filter(p => p < min || p > max); + if (outliers.length === 0) { + min = Math.min(...points); + max = Math.max(...points); + } const binWidth = 2 * IQR * (sampleSize - outliers.length) ** (-1 / 3); const binCount = Math.round((max - min) / binWidth); const actualBinWidth = (max - min) / binCount; diff --git a/packages/visx-stats/test/computeStats.test.ts b/packages/visx-stats/test/computeStats.test.ts index a1ce68586..0a2dd484c 100644 --- a/packages/visx-stats/test/computeStats.test.ts +++ b/packages/visx-stats/test/computeStats.test.ts @@ -19,4 +19,10 @@ describe('computeStats', () => { expect(stats.boxPlot).toBeDefined(); expect(stats.binData).toBeDefined(); }); + + test('min/max should match the dataset when there are no outliers', () => { + const stats = computeStats(edgeCaseData); + expect(stats.boxPlot.min).toBe(Math.min(...edgeCaseData)); + expect(stats.boxPlot.max).toBe(Math.max(...edgeCaseData)); + }); });