1 /** 2 * Returns a histogram operator for the specified data, with an optional 3 * accessor function. If the data specified is not an array of numbers, an 4 * accessor function must be specified to map the data to numeric values. 5 * 6 * @class Represents a histogram operator. 7 * 8 * @param {array} data an array of numbers or objects. 9 * @param {function} [f] an optional accessor function. 10 */ 11 pv.histogram = function(data, f) { 12 var frequency = true; 13 return { 14 15 /** 16 * Returns the computed histogram bins. An optional array of numbers, 17 * <tt>ticks</tt>, may be specified as the break points. If the ticks are 18 * not specified, default ticks will be computed using a linear scale on the 19 * data domain. 20 * 21 * <p>The returned array contains {@link pv.histogram.Bin}s. The <tt>x</tt> 22 * attribute corresponds to the bin's start value (inclusive), while the 23 * <tt>dx</tt> attribute stores the bin size (end - start). The <tt>y</tt> 24 * attribute stores either the frequency count or probability, depending on 25 * how the histogram operator has been configured. 26 * 27 * <p>The {@link pv.histogram.Bin} objects are themselves arrays, containing 28 * the data elements present in each bin, i.e., the elements in the 29 * <tt>data</tt> array (prior to invoking the accessor function, if any). 30 * For example, if the data represented countries, and the accessor function 31 * returned the GDP of each country, the returned bins would be arrays of 32 * countries (not GDPs). 33 * 34 * @function 35 * @name pv.histogram.prototype.bins 36 * @param {array} [ticks] 37 * @returns {array} 38 */ /** @private */ 39 bins: function(ticks) { 40 var x = pv.map(data, f), bins = []; 41 42 /* Initialize default ticks. */ 43 if (!arguments.length) ticks = pv.Scale.linear(x).ticks(); 44 45 /* Initialize the bins. */ 46 for (var i = 0; i < ticks.length - 1; i++) { 47 var bin = bins[i] = []; 48 bin.x = ticks[i]; 49 bin.dx = ticks[i + 1] - ticks[i]; 50 bin.y = 0; 51 } 52 53 /* Count the number of samples per bin. */ 54 for (var i = 0; i < x.length; i++) { 55 var j = pv.search.index(ticks, x[i]) - 1, 56 bin = bins[Math.max(0, Math.min(bins.length - 1, j))]; 57 bin.y++; 58 bin.push(data[i]); 59 } 60 61 /* Convert frequencies to probabilities. */ 62 if (!frequency) for (var i = 0; i < bins.length; i++) { 63 bins[i].y /= x.length; 64 } 65 66 return bins; 67 }, 68 69 /** 70 * Sets or gets whether this histogram operator returns frequencies or 71 * probabilities. 72 * 73 * @function 74 * @name pv.histogram.prototype.frequency 75 * @param {boolean} [x] 76 * @returns {pv.histogram} this. 77 */ /** @private */ 78 frequency: function(x) { 79 if (arguments.length) { 80 frequency = Boolean(x); 81 return this; 82 } 83 return frequency; 84 } 85 }; 86 }; 87 88 /** 89 * @class Represents a bin returned by the {@link pv.histogram} operator. Bins 90 * are themselves arrays containing the data elements present in the given bin 91 * (prior to the accessor function being invoked to convert the data object to a 92 * numeric value). These bin arrays have additional attributes with meta 93 * information about the bin. 94 * 95 * @name pv.histogram.Bin 96 * @extends array 97 * @see pv.histogram 98 */ 99 100 /** 101 * The start value of the bin's range. 102 * 103 * @type number 104 * @name pv.histogram.Bin.prototype.x 105 */ 106 107 /** 108 * The magnitude value of the bin's range; end - start. 109 * 110 * @type number 111 * @name pv.histogram.Bin.prototype.dx 112 */ 113 114 /** 115 * The frequency or probability of the bin, depending on how the histogram 116 * operator was configured. 117 * 118 * @type number 119 * @name pv.histogram.Bin.prototype.y 120 */ 121