prepareBoxplotData.js 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. var quantile = require("./quantile");
  2. var numberUtil = require("../../lib/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. function _default(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 ? min : Math.max(min, Q1 - bound);
  46. var high = useExtreme ? max : Math.min(max, Q3 + bound);
  47. boxData.push([low, Q1, Q2, Q3, high]);
  48. for (var j = 0; j < ascList.length; j++) {
  49. var dataItem = ascList[j];
  50. if (dataItem < low || dataItem > high) {
  51. var outlier = [i, dataItem];
  52. opt.layout === 'vertical' && outlier.reverse();
  53. outliers.push(outlier);
  54. }
  55. }
  56. }
  57. return {
  58. boxData: boxData,
  59. outliers: outliers,
  60. axisData: axisData
  61. };
  62. }
  63. module.exports = _default;