boxplot.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. var __rest = (this && this.__rest) || function (s, e) {
  2. var t = {};
  3. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
  4. t[p] = s[p];
  5. if (s != null && typeof Object.getOwnPropertySymbols === "function")
  6. for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  7. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
  8. t[p[i]] = s[p[i]];
  9. }
  10. return t;
  11. };
  12. import { min as d3Min, max as d3Max, quantile, group } from 'd3-array';
  13. import { subObject } from '../utils/helper';
  14. import { maybeAnimation, subTooltip } from '../utils/mark';
  15. function min(I, V) {
  16. return d3Min(I, (i) => V[i]);
  17. }
  18. function max(I, V) {
  19. return d3Max(I, (i) => V[i]);
  20. }
  21. function lower(I, V) {
  22. const lo = q1(I, V) * 2.5 - q3(I, V) * 1.5;
  23. return d3Min(I, (i) => (V[i] >= lo ? V[i] : NaN));
  24. }
  25. function q1(I, V) {
  26. return quantile(I, 0.25, (i) => V[i]);
  27. }
  28. function q2(I, V) {
  29. return quantile(I, 0.5, (i) => V[i]);
  30. }
  31. function q3(I, V) {
  32. return quantile(I, 0.75, (i) => V[i]);
  33. }
  34. function upper(I, V) {
  35. const hi = q3(I, V) * 2.5 - q1(I, V) * 1.5;
  36. return d3Max(I, (i) => (V[i] <= hi ? V[i] : NaN));
  37. }
  38. /**
  39. * Group marks by x and reserve outlier indexes.
  40. */
  41. function OutlierY() {
  42. return (I, mark) => {
  43. const { encode } = mark;
  44. const { y, x } = encode;
  45. const { value: V } = y;
  46. const { value: X } = x;
  47. const GI = Array.from(group(I, (i) => X[+i]).values());
  48. const FI = GI.flatMap((I) => {
  49. const lo = lower(I, V);
  50. const hi = upper(I, V);
  51. return I.filter((i) => V[i] < lo || V[i] > hi);
  52. });
  53. return [FI, mark];
  54. };
  55. }
  56. export const Boxplot = (options) => {
  57. return () => {
  58. const { data, encode, style = {}, tooltip = {}, transform, animate } = options, rest = __rest(options, ["data", "encode", "style", "tooltip", "transform", "animate"]);
  59. const { point = true } = style, restStyle = __rest(style, ["point"]);
  60. const { y } = encode;
  61. const encodeY = { y, y1: y, y2: y, y3: y, y4: y };
  62. const qy = { y1: q1, y2: q2, y3: q3 };
  63. // Tooltips.
  64. const boxTooltip = subTooltip(tooltip, 'box', {
  65. items: [
  66. { channel: 'y', name: 'min' },
  67. { channel: 'y1', name: 'q1' },
  68. { channel: 'y2', name: 'q2' },
  69. { channel: 'y3', name: 'q3' },
  70. { channel: 'y4', name: 'max' },
  71. ],
  72. }, true);
  73. const pointTooltip = subTooltip(tooltip, 'point', {
  74. title: { channel: 'x' },
  75. items: [{ name: 'outlier', channel: 'y' }],
  76. });
  77. // Only show min and max instead of lower and upper.
  78. // Only draw a box.
  79. if (!point) {
  80. return [
  81. Object.assign({ type: 'box', data: data, transform: [
  82. Object.assign(Object.assign({ type: 'groupX', y: min }, qy), { y4: max }),
  83. ], encode: Object.assign(Object.assign({}, encode), encodeY), style: restStyle, tooltip: boxTooltip }, rest),
  84. ];
  85. }
  86. const boxStyle = subObject(restStyle, 'box');
  87. const pointStyle = subObject(restStyle, 'point');
  88. return [
  89. Object.assign({ type: 'box', data: data, transform: [
  90. Object.assign(Object.assign({ type: 'groupX', y: lower }, qy), { y4: upper }),
  91. ], encode: Object.assign(Object.assign({}, encode), encodeY), style: boxStyle, tooltip: boxTooltip, animate: maybeAnimation(animate, 'box') }, rest),
  92. // Draw outliers.
  93. {
  94. type: 'point',
  95. data: data,
  96. transform: [{ type: OutlierY }],
  97. encode,
  98. style: Object.assign({}, pointStyle),
  99. tooltip: pointTooltip,
  100. animate: maybeAnimation(animate, 'point'),
  101. },
  102. ];
  103. };
  104. };
  105. Boxplot.props = {};
  106. //# sourceMappingURL=boxplot.js.map