From abde4da83deb737c05ab6a082d6c199a0a0a1f00 Mon Sep 17 00:00:00 2001 From: visiky <736929286@qq.com> Date: Sun, 30 May 2021 12:44:05 +0800 Subject: [PATCH] =?UTF-8?q?test(violin):=20=E4=BF=AE=E5=A4=8D=E5=8D=95?= =?UTF-8?q?=E6=B5=8B=E9=97=AE=E9=A2=98=20&=20=E5=A2=9E=E5=8A=A0=E5=8D=95?= =?UTF-8?q?=E6=B5=8B=E8=A6=86=E7=9B=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __tests__/unit/plots/violin/box-spec.ts | 32 ++---------- .../unit/utils/transform/quantile-spec.ts | 50 +++++++++++++++++++ src/utils/transform/quantile.ts | 12 +++-- 3 files changed, 62 insertions(+), 32 deletions(-) create mode 100644 __tests__/unit/utils/transform/quantile-spec.ts diff --git a/__tests__/unit/plots/violin/box-spec.ts b/__tests__/unit/plots/violin/box-spec.ts index b02c151705..ec049e4c3c 100644 --- a/__tests__/unit/plots/violin/box-spec.ts +++ b/__tests__/unit/plots/violin/box-spec.ts @@ -25,14 +25,15 @@ describe('violin', () => { violin.destroy(); }); - it("should not render box views when 'box' set to false.", () => { + // 暂时不开放 box 配置 + it.skip("should not render box views when 'box' set to false.", () => { const violin = new Violin(createDiv(), { width: 400, height: 500, data: BASE_VIOLIN_DATA, xField: 'type', yField: 'value', - box: false, + // box: false, }); violin.render(); @@ -46,31 +47,4 @@ describe('violin', () => { violin.destroy(); }); - - it('should not render box with custom textMap.', () => { - const textMap = { - max: '最大值', - min: '最小值', - median: '中位值', - q1: '上四分位点', - q3: '下四分位点', - }; - const violin = new Violin(createDiv(), { - width: 400, - height: 500, - data: BASE_VIOLIN_DATA, - xField: 'type', - yField: 'value', - box: { - textMap, - }, - }); - - violin.render(); - - // @ts-ignore - expect(violin.options.box.textMap).toEqual(textMap); - - violin.destroy(); - }); }); diff --git a/__tests__/unit/utils/transform/quantile-spec.ts b/__tests__/unit/utils/transform/quantile-spec.ts new file mode 100644 index 0000000000..68f095601b --- /dev/null +++ b/__tests__/unit/utils/transform/quantile-spec.ts @@ -0,0 +1,50 @@ +import { quantile, quantileSorted, quickselect, swap } from '../../../../src/utils/transform/quantile'; + +describe('quantile', () => { + it('quantile-sorted', () => { + expect(quantileSorted([3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20], 0.5)).toBe(9); + }); + + it('quick-select', () => { + const arr = [65, 28, 59, 33, 21, 56, 22, 95, 50, 12, 90, 53, 28, 77, 39]; + quickselect(arr, 8); + expect(arr).toEqual([39, 28, 28, 33, 21, 12, 22, 50, 53, 56, 59, 65, 90, 77, 95]); + }); + + it('quantile', () => { + expect(quantile([3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20], 0.5)).toBe(9); // => 9 + + // from https://github.com/simple-statistics + const even = [3, 6, 7, 8, 8, 10, 13, 15, 16, 20]; + expect(quantile(even, 0.25)).toBe(7); + expect(quantile(even, 0.5)).toBe(9); + expect(quantile(even, 0.75)).toBe(15); + + const odd = [3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20]; + expect(quantile(odd, 0.25)).toBe(7); + expect(quantile(odd, 0.5)).toBe(9); + expect(quantile(odd, 0.75)).toBe(15); + }); + + it('quantile: throw error', () => { + const testEmptyArray = () => quantile([], 0.5); + expect(testEmptyArray).toThrowError(); + + const testBadBounds = () => quantile([1, 2, 3], 1.1); + expect(testBadBounds).toThrowError(); + }); + + it('quantile: can get an array of quantiles on a small number of elements', () => { + const input = [500, 468, 454, 469]; + expect(quantile(input, [0.25, 0.5, 0.75])).toEqual([461, 468.5, 484.5]); + expect(quantile(input, [0.05, 0.25, 0.5, 0.75, 0.95])).toEqual([454, 461, 468.5, 484.5, 500]); + }); + + it('swap', () => { + const arr = [1, 2, 3]; + swap(arr, 0, 2); + expect(arr).toEqual([3, 2, 1]); + swap(arr, 0, 2); + expect(arr).toEqual([1, 2, 3]); + }); +}); diff --git a/src/utils/transform/quantile.ts b/src/utils/transform/quantile.ts index a99d822e98..a57547482b 100644 --- a/src/utils/transform/quantile.ts +++ b/src/utils/transform/quantile.ts @@ -13,7 +13,7 @@ * @example * quantileSorted([3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20], 0.5); // => 9 */ -function quantileSorted(x, p) { +export function quantileSorted(x: number[], p: number) { const idx = x.length * p; if (x.length === 0) { throw new Error('quantile requires at least one data point.'); @@ -39,7 +39,13 @@ function quantileSorted(x, p) { } } -function swap(arr, i, j) { +/** + * 交换数组位置 + * @param arr T[] + * @param i number + * @param j number + */ +export function swap(arr: T[], i: number, j: number): void { const tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; @@ -61,7 +67,7 @@ function swap(arr, i, j) { * quickselect(arr, 8); * // = [39, 28, 28, 33, 21, 12, 22, 50, 53, 56, 59, 65, 90, 77, 95] */ -function quickselect(arr, k, left, right) { +export function quickselect(arr: number[], k, left?: number, right?: number): void { left = left || 0; right = right || arr.length - 1;