prepareBoxplotData.js 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import quantile from './quantile';
  2. import * as numberUtil from '../../src/util/number';
  3. /**
  4. * See:
  5. * <https://en.wikipedia.org/wiki/Box_plot#cite_note-frigge_hoaglin_iglewicz-2>
  6. * <http://stat.ethz.ch/R-manual/R-devel/library/grDevices/html/boxplot.stats.html>
  7. *
  8. * Helper method for preparing data.
  9. *
  10. * @param {Array.<number>} rawData like
  11. * [
  12. * [12,232,443], (raw data set for the first box)
  13. * [3843,5545,1232], (raw datat set for the second box)
  14. * ...
  15. * ]
  16. * @param {Object} [opt]
  17. *
  18. * @param {(number|string)} [opt.boundIQR=1.5] Data less than min bound is outlier.
  19. * default 1.5, means Q1 - 1.5 * (Q3 - Q1).
  20. * If 'none'/0 passed, min bound will not be used.
  21. * @param {(number|string)} [opt.layout='horizontal']
  22. * Box plot layout, can be 'horizontal' or 'vertical'
  23. * @return {Object} {
  24. * boxData: Array.<Array.<number>>
  25. * outliers: Array.<Array.<number>>
  26. * axisData: Array.<string>
  27. * }
  28. */
  29. export default function (rawData, opt) {
  30. opt = opt || [];
  31. var boxData = [];
  32. var outliers = [];
  33. var axisData = [];
  34. var boundIQR = opt.boundIQR;
  35. var useExtreme = boundIQR === 'none' || boundIQR === 0;
  36. for (var i = 0; i < rawData.length; i++) {
  37. axisData.push(i + '');
  38. var ascList = numberUtil.asc(rawData[i].slice());
  39. var Q1 = quantile(ascList, 0.25);
  40. var Q2 = quantile(ascList, 0.5);
  41. var Q3 = quantile(ascList, 0.75);
  42. var min = ascList[0];
  43. var max = ascList[ascList.length - 1];
  44. var bound = (boundIQR == null ? 1.5 : boundIQR) * (Q3 - Q1);
  45. var low = useExtreme
  46. ? min
  47. : Math.max(min, Q1 - bound);
  48. var high = useExtreme
  49. ? max
  50. : Math.min(max, Q3 + bound);
  51. boxData.push([low, Q1, Q2, Q3, high]);
  52. for (var j = 0; j < ascList.length; j++) {
  53. var dataItem = ascList[j];
  54. if (dataItem < low || dataItem > high) {
  55. var outlier = [i, dataItem];
  56. opt.layout === 'vertical' && outlier.reverse();
  57. outliers.push(outlier);
  58. }
  59. }
  60. }
  61. return {
  62. boxData: boxData,
  63. outliers: outliers,
  64. axisData: axisData
  65. };
  66. }