diff --git a/src/quantile.js b/src/quantile.js index 75d9726..f4a8a48 100644 --- a/src/quantile.js +++ b/src/quantile.js @@ -38,8 +38,8 @@ export function quantileIndex(values, p, valueof = number) { if (p <= 0) return minIndex(numbers); if (p >= 1) return maxIndex(numbers); var numbers, - index = Uint32Array.from(values, (_, i) => i), - j = numbers.length - 1, + index = Uint32Array.from(values, (_, i) => i).filter(i => !isNaN(numbers[i])), + j = index.length - 1, i = Math.floor(j * p); quickselect(index, i, 0, j, (i, j) => ascendingDefined(numbers[i], numbers[j])); i = greatest(index.subarray(0, i + 1), (i) => numbers[i]); diff --git a/test/median-test.js b/test/median-test.js index 78d93f3..3818121 100644 --- a/test/median-test.js +++ b/test/median-test.js @@ -98,6 +98,11 @@ it("median(array, f) uses the undefined context", () => { assert.deepStrictEqual(results, [undefined, undefined]); }); +it("medianIndex(array) excludes missing values from the median rank", () => { + assert.strictEqual(medianIndex([0, null, 100]), 0); + assert.strictEqual(medianIndex([undefined, 0, 100]), 1); +}); + it("medianIndex(array) returns the index", () => { assert.deepStrictEqual(medianIndex([1, 2]), 0); assert.deepStrictEqual(medianIndex([1, 2, 3]), 1); diff --git a/test/quantile-test.js b/test/quantile-test.js index 4b0d0ec..288b669 100644 --- a/test/quantile-test.js +++ b/test/quantile-test.js @@ -122,6 +122,16 @@ it("quantileIndex(array, 0.5) handles undefined values", () => { assert.deepStrictEqual(quantileIndex([1, 1, 1, null, 2, 3, 3, 3], 0.5, (d) => d), 4); }); +it("quantileIndex(array, p) excludes missing values from the quantile rank", () => { + for (const missing of [null, undefined, NaN]) { + assert.strictEqual(quantileIndex([0, missing, 100], 0.5), 0); + assert.strictEqual(quantileIndex([missing, 0, 100], 0.5), 1); + assert.strictEqual(quantileIndex([0, 100, missing], 0.5), 0); + } + assert.strictEqual(quantileIndex([{v: 0}, {}, {v: 100}], 0.5, d => d.v), 0); + assert.strictEqual(quantileIndex([null, undefined, NaN], 0.5), -1); +}); + it("quantileIndex(array, 0.5) returns the first of equivalent values", () => { assert.deepStrictEqual(quantileIndex([1, 1, 1, 2, 2, 3, 3, 3], 0.5), 4); });