Skip to content

Commit cdd37e4

Browse files
authored
better degenerate thresholds (#271)
1 parent 7952835 commit cdd37e4

7 files changed

Lines changed: 35 additions & 3 deletions

File tree

src/threshold/freedmanDiaconis.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ import count from "../count.js";
22
import quantile from "../quantile.js";
33

44
export default function thresholdFreedmanDiaconis(values, min, max) {
5-
return Math.ceil((max - min) / (2 * (quantile(values, 0.75) - quantile(values, 0.25)) * Math.pow(count(values), -1 / 3)));
5+
const c = count(values), d = quantile(values, 0.75) - quantile(values, 0.25);
6+
return c && d ? Math.ceil((max - min) / (2 * d * Math.pow(c, -1 / 3))) : 1;
67
}

src/threshold/scott.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ import count from "../count.js";
22
import deviation from "../deviation.js";
33

44
export default function thresholdScott(values, min, max) {
5-
return Math.ceil((max - min) * Math.cbrt(count(values)) / (3.49 * deviation(values)));
5+
const c = count(values), d = deviation(values);
6+
return c && d ? Math.ceil((max - min) * Math.cbrt(c) / (3.49 * d)) : 1;
67
}

src/threshold/sturges.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import count from "../count.js";
22

33
export default function thresholdSturges(values) {
4-
return Math.ceil(Math.log(count(values)) / Math.LN2) + 1;
4+
return Math.max(1, Math.ceil(Math.log(count(values)) / Math.LN2) + 1);
55
}

test/deviation-test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import assert from "assert";
22
import {deviation} from "../src/index.js";
33

44
it("deviation(array) returns the standard deviation of the specified numbers", () => {
5+
assert.strictEqual(deviation([1, 1, 1, 1, 1]), 0);
56
assert.strictEqual(deviation([5, 1, 2, 3, 4]), Math.sqrt(2.5));
67
assert.strictEqual(deviation([20, 3]), Math.sqrt(144.5));
78
assert.strictEqual(deviation([3, 20]), Math.sqrt(144.5));

test/threshold/freedmanDiaconic-test.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,15 @@ import {thresholdFreedmanDiaconis} from "../../src/index.js";
44
it("thresholdFreedmanDiaconis(values, min, max) returns the expected result", () => {
55
assert.strictEqual(thresholdFreedmanDiaconis([4, 3, 2, 1, NaN], 1, 4), 2);
66
});
7+
8+
it("thresholdFreedmanDiaconis(values, min, max) handles values with zero deviation", () => {
9+
assert.strictEqual(thresholdFreedmanDiaconis([1, 1, 1, 1], 1, 4), 1);
10+
});
11+
12+
it("thresholdFreedmanDiaconis(values, min, max) handles single-value arrays", () => {
13+
assert.strictEqual(thresholdFreedmanDiaconis([1], 1, 4), 1);
14+
});
15+
16+
it("thresholdFreedmanDiaconis(values, min, max) handles empty arrays", () => {
17+
assert.strictEqual(thresholdFreedmanDiaconis([], 1, 4), 1);
18+
});

test/threshold/scott-test.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,15 @@ import {thresholdScott} from "../../src/index.js";
44
it("thresholdScott(values, min, max) returns the expected result", () => {
55
assert.strictEqual(thresholdScott([4, 3, 2, 1, NaN], 1, 4), 2);
66
});
7+
8+
it("thresholdScott(values, min, max) handles values with zero deviation", () => {
9+
assert.strictEqual(thresholdScott([1, 1, 1, 1], 1, 4), 1);
10+
});
11+
12+
it("thresholdScott(values, min, max) handles single-value arrays", () => {
13+
assert.strictEqual(thresholdScott([1], 1, 4), 1);
14+
});
15+
16+
it("thresholdScott(values, min, max) handles empty arrays", () => {
17+
assert.strictEqual(thresholdScott([], 1, 4), 1);
18+
});

test/threshold/sturges-test.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,9 @@ import {thresholdSturges} from "../../src/index.js";
33

44
it("thresholdSturges(values, min, max) returns the expected result", () => {
55
assert.strictEqual(thresholdSturges([4, 3, 2, 1, NaN], 1, 4), 3);
6+
assert.strictEqual(thresholdSturges([1], 1, 4), 1);
7+
});
8+
9+
it("thresholdSturges(values, min, max) handles empty arrays", () => {
10+
assert.strictEqual(thresholdSturges([], 1, 4), 1);
611
});

0 commit comments

Comments
 (0)