bin.js 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. "use strict";
  2. var __rest = (this && this.__rest) || function (s, e) {
  3. var t = {};
  4. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
  5. t[p] = s[p];
  6. if (s != null && typeof Object.getOwnPropertySymbols === "function")
  7. for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  8. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
  9. t[p[i]] = s[p[i]];
  10. }
  11. return t;
  12. };
  13. Object.defineProperty(exports, "__esModule", { value: true });
  14. exports.Bin = void 0;
  15. const d3_array_1 = require("d3-array");
  16. const helper_1 = require("../utils/helper");
  17. const groupN_1 = require("./groupN");
  18. const helper_2 = require("./utils/helper");
  19. const THRESHOLD = 'thresholds';
  20. /**
  21. * @see https://github.com/observablehq/plot/blob/main/src/transforms/bin.js
  22. */
  23. function thresholdAuto(values) {
  24. const [min, max] = (0, d3_array_1.extent)(values);
  25. return Math.min(200, (0, d3_array_1.thresholdScott)(values, min, max));
  26. }
  27. /**
  28. * The Bin aggregate data.
  29. * @todo More threshold method.
  30. * @todo Performance.
  31. */
  32. const Bin = (options = {}) => {
  33. const { groupChannels = ['color'], binChannels = ['x', 'y'] } = options, rest = __rest(options, ["groupChannels", "binChannels"]);
  34. const channelIndexKey = {};
  35. // Group indexes and update channelIndexKey.
  36. const groupBy = (I, mark) => {
  37. const { encode } = mark;
  38. const binValues = binChannels.map((channel) => {
  39. const [V] = (0, helper_2.columnOf)(encode, channel);
  40. return V;
  41. });
  42. const thresholds = (0, helper_1.subObject)(rest, THRESHOLD);
  43. const DI = I.filter((i) => binValues.every((V) => (0, helper_1.defined)(V[i])));
  44. // Group indexes by both discrete and quantitative channels.
  45. const groupKeys = [
  46. // For discrete channels, use value as group key.
  47. ...groupChannels
  48. .map((d) => {
  49. const [V] = (0, helper_2.columnOf)(encode, d);
  50. return V;
  51. })
  52. .filter(helper_1.defined)
  53. .map((V) => (i) => V[i]),
  54. // For quantitative channels, use extent of bin as group key.
  55. ...binChannels.map((d, i) => {
  56. const V = binValues[i];
  57. const t = thresholds[d] || thresholdAuto(V);
  58. const bins = (0, d3_array_1.bin)()
  59. .thresholds(t)
  60. .value((i) => +V[i])(DI);
  61. const indexKey = new Map(bins.flatMap((bin) => {
  62. const { x0, x1 } = bin;
  63. const key = `${x0},${x1}`;
  64. return bin.map((i) => [i, key]);
  65. }));
  66. channelIndexKey[d] = indexKey;
  67. return (i) => indexKey.get(i);
  68. }),
  69. ];
  70. // Group by indexes by channel keys.
  71. const key = (i) => groupKeys.map((key) => key(i)).join('-');
  72. return Array.from((0, d3_array_1.group)(DI, key).values());
  73. };
  74. return (0, groupN_1.GroupN)(Object.assign(Object.assign(Object.assign({}, Object.fromEntries(Object.entries(rest).filter(([k]) => !k.startsWith(THRESHOLD)))), Object.fromEntries(binChannels.flatMap((channel) => {
  75. const start = ([i]) => +channelIndexKey[channel].get(i).split(',')[0];
  76. const end = ([i]) => +channelIndexKey[channel].get(i).split(',')[1];
  77. end.from = channel;
  78. return [
  79. [channel, start],
  80. [`${channel}1`, end],
  81. ];
  82. }))), { groupBy }));
  83. };
  84. exports.Bin = Bin;
  85. exports.Bin.props = {};
  86. //# sourceMappingURL=bin.js.map