1 | d3.layout.histogram = function() { |
---|
2 | var frequency = true, |
---|
3 | valuer = Number, |
---|
4 | ranger = d3_layout_histogramRange, |
---|
5 | binner = d3_layout_histogramBinSturges; |
---|
6 | |
---|
7 | function histogram(data, i) { |
---|
8 | var bins = [], |
---|
9 | values = data.map(valuer, this), |
---|
10 | range = ranger.call(this, values, i), |
---|
11 | thresholds = binner.call(this, range, values, i), |
---|
12 | bin, |
---|
13 | i = -1, |
---|
14 | n = values.length, |
---|
15 | m = thresholds.length - 1, |
---|
16 | k = frequency ? 1 : 1 / n, |
---|
17 | x; |
---|
18 | |
---|
19 | // Initialize the bins. |
---|
20 | while (++i < m) { |
---|
21 | bin = bins[i] = []; |
---|
22 | bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]); |
---|
23 | bin.y = 0; |
---|
24 | } |
---|
25 | |
---|
26 | // Fill the bins, ignoring values outside the range. |
---|
27 | i = -1; while(++i < n) { |
---|
28 | x = values[i]; |
---|
29 | if ((x >= range[0]) && (x <= range[1])) { |
---|
30 | bin = bins[d3.bisect(thresholds, x, 1, m) - 1]; |
---|
31 | bin.y += k; |
---|
32 | bin.push(data[i]); |
---|
33 | } |
---|
34 | } |
---|
35 | |
---|
36 | return bins; |
---|
37 | } |
---|
38 | |
---|
39 | // Specifies how to extract a value from the associated data. The default |
---|
40 | // value function is `Number`, which is equivalent to the identity function. |
---|
41 | histogram.value = function(x) { |
---|
42 | if (!arguments.length) return valuer; |
---|
43 | valuer = x; |
---|
44 | return histogram; |
---|
45 | }; |
---|
46 | |
---|
47 | // Specifies the range of the histogram. Values outside the specified range |
---|
48 | // will be ignored. The argument `x` may be specified either as a two-element |
---|
49 | // array representing the minimum and maximum value of the range, or as a |
---|
50 | // function that returns the range given the array of values and the current |
---|
51 | // index `i`. The default range is the extent (minimum and maximum) of the |
---|
52 | // values. |
---|
53 | histogram.range = function(x) { |
---|
54 | if (!arguments.length) return ranger; |
---|
55 | ranger = d3.functor(x); |
---|
56 | return histogram; |
---|
57 | }; |
---|
58 | |
---|
59 | // Specifies how to bin values in the histogram. The argument `x` may be |
---|
60 | // specified as a number, in which case the range of values will be split |
---|
61 | // uniformly into the given number of bins. Or, `x` may be an array of |
---|
62 | // threshold values, defining the bins; the specified array must contain the |
---|
63 | // rightmost (upper) value, thus specifying n + 1 values for n bins. Or, `x` |
---|
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. |
---|
68 | histogram.bins = function(x) { |
---|
69 | if (!arguments.length) return binner; |
---|
70 | binner = typeof x === "number" |
---|
71 | ? function(range) { return d3_layout_histogramBinFixed(range, x); } |
---|
72 | : d3.functor(x); |
---|
73 | return histogram; |
---|
74 | }; |
---|
75 | |
---|
76 | // Specifies whether the histogram's `y` value is a count (frequency) or a |
---|
77 | // probability (density). The default value is true. |
---|
78 | histogram.frequency = function(x) { |
---|
79 | if (!arguments.length) return frequency; |
---|
80 | frequency = !!x; |
---|
81 | return histogram; |
---|
82 | }; |
---|
83 | |
---|
84 | return histogram; |
---|
85 | }; |
---|
86 | |
---|
87 | function d3_layout_histogramBinSturges(range, values) { |
---|
88 | return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1)); |
---|
89 | } |
---|
90 | |
---|
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; |
---|
98 | } |
---|
99 | |
---|
100 | function d3_layout_histogramRange(values) { |
---|
101 | return [d3.min(values), d3.max(values)]; |
---|
102 | } |
---|