From 75691b7b7c43453ddc49687ec5d155e1ae08493a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Sat, 29 May 2021 17:53:19 +0200 Subject: [PATCH 1/6] cap the default number of bins at 200 (see #417) --- README.md | 2 +- src/transforms/bin.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5b8371251f..c393d8586d 100644 --- a/README.md +++ b/README.md @@ -1047,7 +1047,7 @@ The **thresholds** option may be specified as a named method or a variety of oth * a time interval (for temporal binning) * a function that returns an array, count, or time interval -If the **thresholds** option is not specified, it defaults to *scott*. If a function, it is passed three arguments: the array of input values, the domain minimum, and the domain maximum. If a number, [d3.ticks](https://github.com/d3/d3-array/blob/master/README.md#ticks) or [d3.utcTicks](https://github.com/d3/d3-time/blob/master/README.md#ticks) is used to choose suitable nice thresholds. +If the **thresholds** option is not specified, it defaults to *scott*, capped at 200. If a function, it is passed three arguments: the array of input values, the domain minimum, and the domain maximum. If a number, [d3.ticks](https://github.com/d3/d3-array/blob/master/README.md#ticks) or [d3.utcTicks](https://github.com/d3/d3-time/blob/master/README.md#ticks) is used to choose suitable nice thresholds. The bin transform supports grouping in addition to binning: you can subdivide bins by up to two additional ordinal or categorical dimensions (not including faceting). If any of **z**, **fill**, or **stroke** is a channel, the first of these channels will be used to subdivide bins. Similarly, Plot.binX will group on **y** if **y** is not an output channel, and Plot.binY will group on **x** if **x** is not an output channel. For example, for a stacked histogram: diff --git a/src/transforms/bin.js b/src/transforms/bin.js index 6aa9809200..5d3cea8ef5 100644 --- a/src/transforms/bin.js +++ b/src/transforms/bin.js @@ -171,7 +171,10 @@ function maybeBin(options) { return bin; } -function maybeThresholds(thresholds = thresholdScott) { +function maybeThresholds(thresholds) { + if (thresholds === undefined) { + return (...args) => Math.min(200, thresholdScott(...args)); + } if (typeof thresholds === "string") { switch (thresholds.toLowerCase()) { case "freedman-diaconis": return thresholdFreedmanDiaconis; From 21de6ada15e2d351882904fa43f8692825d4ffe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Sat, 29 May 2021 18:44:35 +0200 Subject: [PATCH 2/6] no closure; explicit args --- src/transforms/bin.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/transforms/bin.js b/src/transforms/bin.js index 5d3cea8ef5..057e51dcfb 100644 --- a/src/transforms/bin.js +++ b/src/transforms/bin.js @@ -172,9 +172,7 @@ function maybeBin(options) { } function maybeThresholds(thresholds) { - if (thresholds === undefined) { - return (...args) => Math.min(200, thresholdScott(...args)); - } + if (thresholds === undefined) return thresholdDefault; if (typeof thresholds === "string") { switch (thresholds.toLowerCase()) { case "freedman-diaconis": return thresholdFreedmanDiaconis; @@ -186,6 +184,10 @@ function maybeThresholds(thresholds) { return thresholds; // pass array, count, or function to bin.thresholds } +function thresholdDefault(values, min, max) { + return Math.min(200, thresholdScott(values, min, max)); +} + function isTimeInterval(t) { return t ? typeof t.range === "function" : false; } From b7282a31cb6c20388ad18d8f16ee259cf52be3e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Sat, 29 May 2021 21:43:50 +0200 Subject: [PATCH 3/6] default argument --- src/transforms/bin.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/transforms/bin.js b/src/transforms/bin.js index 057e51dcfb..125f1a2dbf 100644 --- a/src/transforms/bin.js +++ b/src/transforms/bin.js @@ -171,8 +171,7 @@ function maybeBin(options) { return bin; } -function maybeThresholds(thresholds) { - if (thresholds === undefined) return thresholdDefault; +function maybeThresholds(thresholds = thresholdDefault) { if (typeof thresholds === "string") { switch (thresholds.toLowerCase()) { case "freedman-diaconis": return thresholdFreedmanDiaconis; From aaba03b93d9e263a10c897652428e328ca52fc0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Mon, 2 Aug 2021 17:35:45 +0200 Subject: [PATCH 4/6] explicit "auto" thresholds --- README.md | 3 ++- src/transforms/bin.js | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c393d8586d..2a15ba24ab 100644 --- a/README.md +++ b/README.md @@ -1039,6 +1039,7 @@ Plot.binX({y: "count"}, {x: {thresholds: 20, value: "culmen_length_mm"}}) The **thresholds** option may be specified as a named method or a variety of other ways: +* *auto* (default) - Scott’s rule, capped at 200. * *freedman-diaconis* - the [Freedman–Diaconis rule](https://en.wikipedia.org/wiki/Freedman–Diaconis_rule) * *scott* - [Scott’s normal reference rule](https://en.wikipedia.org/wiki/Histogram#Scott.27s_normal_reference_rule) * *sturges* - [Sturges’ formula](https://en.wikipedia.org/wiki/Histogram#Sturges.27_formula) @@ -1047,7 +1048,7 @@ The **thresholds** option may be specified as a named method or a variety of oth * a time interval (for temporal binning) * a function that returns an array, count, or time interval -If the **thresholds** option is not specified, it defaults to *scott*, capped at 200. If a function, it is passed three arguments: the array of input values, the domain minimum, and the domain maximum. If a number, [d3.ticks](https://github.com/d3/d3-array/blob/master/README.md#ticks) or [d3.utcTicks](https://github.com/d3/d3-time/blob/master/README.md#ticks) is used to choose suitable nice thresholds. +If the **thresholds** option is specified as a function, it is passed three arguments: the array of input values, the domain minimum, and the domain maximum. If a number, [d3.ticks](https://github.com/d3/d3-array/blob/master/README.md#ticks) or [d3.utcTicks](https://github.com/d3/d3-time/blob/master/README.md#ticks) is used to choose suitable nice thresholds. The bin transform supports grouping in addition to binning: you can subdivide bins by up to two additional ordinal or categorical dimensions (not including faceting). If any of **z**, **fill**, or **stroke** is a channel, the first of these channels will be used to subdivide bins. Similarly, Plot.binX will group on **y** if **y** is not an output channel, and Plot.binY will group on **x** if **x** is not an output channel. For example, for a stacked histogram: diff --git a/src/transforms/bin.js b/src/transforms/bin.js index 125f1a2dbf..903febf628 100644 --- a/src/transforms/bin.js +++ b/src/transforms/bin.js @@ -177,6 +177,7 @@ function maybeThresholds(thresholds = thresholdDefault) { case "freedman-diaconis": return thresholdFreedmanDiaconis; case "scott": return thresholdScott; case "sturges": return thresholdSturges; + case "auto": return thresholdDefault; } throw new Error("invalid thresholds"); } From 12e695f8fdc03316ea1def72bea1f04832f91379 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Mon, 2 Aug 2021 14:57:50 -0700 Subject: [PATCH 5/6] rename to thresholdAuto --- src/transforms/bin.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/transforms/bin.js b/src/transforms/bin.js index 903febf628..b3e068cc3f 100644 --- a/src/transforms/bin.js +++ b/src/transforms/bin.js @@ -171,20 +171,20 @@ function maybeBin(options) { return bin; } -function maybeThresholds(thresholds = thresholdDefault) { +function maybeThresholds(thresholds = thresholdAuto) { if (typeof thresholds === "string") { switch (thresholds.toLowerCase()) { case "freedman-diaconis": return thresholdFreedmanDiaconis; case "scott": return thresholdScott; case "sturges": return thresholdSturges; - case "auto": return thresholdDefault; + case "auto": return thresholdAuto; } throw new Error("invalid thresholds"); } return thresholds; // pass array, count, or function to bin.thresholds } -function thresholdDefault(values, min, max) { +function thresholdAuto(values, min, max) { return Math.min(200, thresholdScott(values, min, max)); } From 3b863f345c8bdd78d5b78e42e6a0679e988ed1a5 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Mon, 2 Aug 2021 14:58:39 -0700 Subject: [PATCH 6/6] update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2a15ba24ab..af78d9a24f 100644 --- a/README.md +++ b/README.md @@ -1039,7 +1039,7 @@ Plot.binX({y: "count"}, {x: {thresholds: 20, value: "culmen_length_mm"}}) The **thresholds** option may be specified as a named method or a variety of other ways: -* *auto* (default) - Scott’s rule, capped at 200. +* *auto* (default) - Scott’s rule, capped at 200 * *freedman-diaconis* - the [Freedman–Diaconis rule](https://en.wikipedia.org/wiki/Freedman–Diaconis_rule) * *scott* - [Scott’s normal reference rule](https://en.wikipedia.org/wiki/Histogram#Scott.27s_normal_reference_rule) * *sturges* - [Sturges’ formula](https://en.wikipedia.org/wiki/Histogram#Sturges.27_formula)