import "../arrays/bisect"; import "../arrays/min"; import "../arrays/max"; import "../core/functor"; import "layout"; d3.layout.histogram = function() { var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges; function histogram(data, i) { var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x; // Initialize the bins. while (++i < m) { bin = bins[i] = []; bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]); bin.y = 0; } // Fill the bins, ignoring values outside the range. if (m > 0) { i = -1; while(++i < n) { x = values[i]; if (x >= range[0] && x <= range[1]) { bin = bins[d3.bisect(thresholds, x, 1, m) - 1]; bin.y += k; bin.push(data[i]); } } } return bins; } // Specifies how to extract a value from the associated data. The default // value function is `Number`, which is equivalent to the identity function. histogram.value = function(x) { if (!arguments.length) return valuer; valuer = x; return histogram; }; // Specifies the range of the histogram. Values outside the specified range // will be ignored. The argument `x` may be specified either as a two-element // array representing the minimum and maximum value of the range, or as a // function that returns the range given the array of values and the current // index `i`. The default range is the extent (minimum and maximum) of the // values. histogram.range = function(x) { if (!arguments.length) return ranger; ranger = d3_functor(x); return histogram; }; // Specifies how to bin values in the histogram. The argument `x` may be // specified as a number, in which case the range of values will be split // uniformly into the given number of bins. Or, `x` may be an array of // threshold values, defining the bins; the specified array must contain the // rightmost (upper) value, thus specifying n + 1 values for n bins. Or, `x` // may be a function which is evaluated, being passed the range, the array of // values, and the current index `i`, returning an array of thresholds. The // default bin function will divide the values into uniform bins using // Sturges' formula. histogram.bins = function(x) { if (!arguments.length) return binner; binner = typeof x === "number" ? function(range) { return d3_layout_histogramBinFixed(range, x); } : d3_functor(x); return histogram; }; // Specifies whether the histogram's `y` value is a count (frequency) or a // probability (density). The default value is true. histogram.frequency = function(x) { if (!arguments.length) return frequency; frequency = !!x; return histogram; }; return histogram; }; function d3_layout_histogramBinSturges(range, values) { return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1)); } function d3_layout_histogramBinFixed(range, n) { var x = -1, b = +range[0], m = (range[1] - b) / n, f = []; while (++x <= n) f[x] = m * x + b; return f; } function d3_layout_histogramRange(values) { return [d3.min(values), d3.max(values)]; }