Skip to content

Commit ce52261

Browse files
committed
Default bins using Sturges' formula.
1 parent 08a5aa3 commit ce52261

4 files changed

Lines changed: 40 additions & 36 deletions

File tree

d3.layout.js

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -876,13 +876,13 @@ d3.layout.histogram = function() {
876876
var frequency = true,
877877
valuer = Number,
878878
ranger = d3_layout_histogramRange,
879-
binner = d3_layout_histogramBins10;
879+
binner = d3_layout_histogramBinSturges;
880880

881881
function histogram(data, i) {
882882
var bins = [],
883883
values = data.map(valuer, this),
884884
range = ranger.call(this, values, i),
885-
thresholds = binner.call(this, range, i),
885+
thresholds = binner.call(this, range, values, i),
886886
bin,
887887
i = -1,
888888
n = values.length,
@@ -897,7 +897,7 @@ d3.layout.histogram = function() {
897897
bin.y = 0;
898898
}
899899

900-
// Fill the bins.
900+
// Fill the bins, ignoring values outside the range.
901901
i = -1; while(++i < n) {
902902
x = values[i];
903903
if ((x >= range[0]) && (x <= range[1])) {
@@ -935,12 +935,15 @@ d3.layout.histogram = function() {
935935
// uniformly into the given number of bins. Or, `x` may be an array of
936936
// threshold values, defining the bins; the specified array must contain the
937937
// rightmost (upper) value, thus specifying n + 1 values for n bins. Or, `x`
938-
// may be a function which is evaluated, being passed the array of values and
939-
// the current index `i`, returning an array of thresholds. The default bin
940-
// function will divide the values into ten uniform bins.
938+
// may be a function which is evaluated, being passed the range, the array of
939+
// values, and the current index `i`, returning an array of thresholds. The
940+
// default bin function will divide the values into uniform bins using
941+
// Sturges' formula.
941942
histogram.bins = function(x) {
942943
if (!arguments.length) return binner;
943-
binner = typeof x === "number" ? d3_layout_histogramBins(x) : d3.functor(x);
944+
binner = typeof x === "number"
945+
? function(range) { return d3_layout_histogramBinFixed(range, x); }
946+
: d3.functor(x);
944947
return histogram;
945948
};
946949

@@ -955,17 +958,17 @@ d3.layout.histogram = function() {
955958
return histogram;
956959
};
957960

958-
var d3_layout_histogramBins10 = d3_layout_histogramBins(10);
961+
function d3_layout_histogramBinSturges(range, values) {
962+
return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));
963+
}
959964

960-
function d3_layout_histogramBins(n) {
961-
return function(range) {
962-
var x = -1,
963-
b = +range[0],
964-
m = (range[1] - b) / n,
965-
f = [];
966-
while (++x <= n) f[x] = m * x + b;
967-
return f;
968-
};
965+
function d3_layout_histogramBinFixed(range, n) {
966+
var x = -1,
967+
b = +range[0],
968+
m = (range[1] - b) / n,
969+
f = [];
970+
while (++x <= n) f[x] = m * x + b;
971+
return f;
969972
}
970973

971974
function d3_layout_histogramRange(values) {

d3.layout.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/histogram/histogram.html

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@
4141
h = 400;
4242

4343
var histogram = d3.layout.histogram()
44-
.frequency(true)
45-
.bins(40)
4644
(data);
4745

4846
var x = d3.scale.ordinal()

src/layout/histogram.js

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ d3.layout.histogram = function() {
22
var frequency = true,
33
valuer = Number,
44
ranger = d3_layout_histogramRange,
5-
binner = d3_layout_histogramBins10;
5+
binner = d3_layout_histogramBinSturges;
66

77
function histogram(data, i) {
88
var bins = [],
99
values = data.map(valuer, this),
1010
range = ranger.call(this, values, i),
11-
thresholds = binner.call(this, range, i),
11+
thresholds = binner.call(this, range, values, i),
1212
bin,
1313
i = -1,
1414
n = values.length,
@@ -61,12 +61,15 @@ d3.layout.histogram = function() {
6161
// uniformly into the given number of bins. Or, `x` may be an array of
6262
// threshold values, defining the bins; the specified array must contain the
6363
// rightmost (upper) value, thus specifying n + 1 values for n bins. Or, `x`
64-
// may be a function which is evaluated, being passed the array of values and
65-
// the current index `i`, returning an array of thresholds. The default bin
66-
// function will divide the values into ten uniform bins.
64+
// may be a function which is evaluated, being passed the range, the array of
65+
// values, and the current index `i`, returning an array of thresholds. The
66+
// default bin function will divide the values into uniform bins using
67+
// Sturges' formula.
6768
histogram.bins = function(x) {
6869
if (!arguments.length) return binner;
69-
binner = typeof x === "number" ? d3_layout_histogramBins(x) : d3.functor(x);
70+
binner = typeof x === "number"
71+
? function(range) { return d3_layout_histogramBinFixed(range, x); }
72+
: d3.functor(x);
7073
return histogram;
7174
};
7275

@@ -81,17 +84,17 @@ d3.layout.histogram = function() {
8184
return histogram;
8285
};
8386

84-
var d3_layout_histogramBins10 = d3_layout_histogramBins(10);
87+
function d3_layout_histogramBinSturges(range, values) {
88+
return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));
89+
}
8590

86-
function d3_layout_histogramBins(n) {
87-
return function(range) {
88-
var x = -1,
89-
b = +range[0],
90-
m = (range[1] - b) / n,
91-
f = [];
92-
while (++x <= n) f[x] = m * x + b;
93-
return f;
94-
};
91+
function d3_layout_histogramBinFixed(range, n) {
92+
var x = -1,
93+
b = +range[0],
94+
m = (range[1] - b) / n,
95+
f = [];
96+
while (++x <= n) f[x] = m * x + b;
97+
return f;
9598
}
9699

97100
function d3_layout_histogramRange(values) {

0 commit comments

Comments
 (0)