histogram.js 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import {slice} from "./array";
  2. import bisect from "./bisect";
  3. import constant from "./constant";
  4. import extent from "./extent";
  5. import identity from "./identity";
  6. import range from "./range";
  7. import {tickStep} from "./ticks";
  8. import sturges from "./threshold/sturges";
  9. export default function() {
  10. var value = identity,
  11. domain = extent,
  12. threshold = sturges;
  13. function histogram(data) {
  14. var i,
  15. n = data.length,
  16. x,
  17. values = new Array(n);
  18. for (i = 0; i < n; ++i) {
  19. values[i] = value(data[i], i, data);
  20. }
  21. var xz = domain(values),
  22. x0 = xz[0],
  23. x1 = xz[1],
  24. tz = threshold(values, x0, x1);
  25. // Convert number of thresholds into uniform thresholds.
  26. if (!Array.isArray(tz)) {
  27. tz = tickStep(x0, x1, tz);
  28. tz = range(Math.ceil(x0 / tz) * tz, x1, tz); // exclusive
  29. }
  30. // Remove any thresholds outside the domain.
  31. var m = tz.length;
  32. while (tz[0] <= x0) tz.shift(), --m;
  33. while (tz[m - 1] > x1) tz.pop(), --m;
  34. var bins = new Array(m + 1),
  35. bin;
  36. // Initialize bins.
  37. for (i = 0; i <= m; ++i) {
  38. bin = bins[i] = [];
  39. bin.x0 = i > 0 ? tz[i - 1] : x0;
  40. bin.x1 = i < m ? tz[i] : x1;
  41. }
  42. // Assign data to bins by value, ignoring any outside the domain.
  43. for (i = 0; i < n; ++i) {
  44. x = values[i];
  45. if (x0 <= x && x <= x1) {
  46. bins[bisect(tz, x, 0, m)].push(data[i]);
  47. }
  48. }
  49. return bins;
  50. }
  51. histogram.value = function(_) {
  52. return arguments.length ? (value = typeof _ === "function" ? _ : constant(_), histogram) : value;
  53. };
  54. histogram.domain = function(_) {
  55. return arguments.length ? (domain = typeof _ === "function" ? _ : constant([_[0], _[1]]), histogram) : domain;
  56. };
  57. histogram.thresholds = function(_) {
  58. return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), histogram) : threshold;
  59. };
  60. return histogram;
  61. }