toolkit/javascript/d3/src/layout/histogram.js
changeset 47 c0b4a8b5a012
equal deleted inserted replaced
46:efd9c589177a 47:c0b4a8b5a012
       
     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 }