New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

echarts-stat

Package Overview
Dependencies
Maintainers
2
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

echarts-stat - npm Package Compare versions

Comparing version 1.1.1 to 1.2.0

src/transform/clustering.js

2

dist/ecStat.min.js

@@ -1,1 +0,1 @@

!function(r,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.ecStat=t():r.ecStat=t()}(this,function(){return function(r){function t(e){if(n[e])return n[e].exports;var o=n[e]={exports:{},id:e,loaded:!1};return r[e].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=r,t.c=n,t.p="",t(0)}([function(r,t,n){var e;e=function(r){return{clustering:n(11),regression:n(13),statistics:n(14),histogram:n(12)}}.call(t,n,t,r),!(void 0!==e&&(r.exports=e))},function(r,t,n){var e;e=function(r){function t(r){return r=null===r?NaN:+r,"number"==typeof r&&!isNaN(r)}function n(r){return isFinite(r)&&r===Math.round(r)}return{isNumber:t,isInteger:n}}.call(t,n,t,r),!(void 0!==e&&(r.exports=e))},function(r,t,n){var e;e=function(r){function t(r){if(!a(r))throw new Error("Invalid data type, you should input an array");var t=[],n=u(r);if(1===n.length)for(var e=0;e<n[0];e++)f(r[e])&&t.push(r[e]);else if(2===n.length)for(var e=0;e<n[0];e++){for(var o=!0,i=0;i<n[1];i++)f(r[e][i])||(o=!1);o&&t.push(r[e])}return t}function e(r){var t=r.toString(),n=t.indexOf(".");return n<0?0:t.length-1-n}var o=n(4),a=o.isArray,u=o.size,i=n(1),f=i.isNumber;return{dataPreprocess:t,getPrecision:e}}.call(t,n,t,r),!(void 0!==e&&(r.exports=e))},function(r,t,n){var e;e=function(r){return function(r,t){var n=r.length;if(!n)return 0;if(t<=0||n<2)return r[0];if(t>=1)return r[n-1];var e=(n-1)*t,o=Math.floor(e),a=r[o],u=r[o+1];return a+(u-a)*(e-o)}}.call(t,n,t,r),!(void 0!==e&&(r.exports=e))},function(r,t,n){var e;e=function(r){function t(r){for(var t=[];n(r);)t.push(r.length),r=r[0];return t}function n(r){return"[object Array]"===l.call(r)}function e(r,t){for(var n=[],e=0;e<r;e++){n[e]=[];for(var o=0;o<t;o++)n[e][o]=0}return n}function o(r){for(var t=0,n=0;n<r.length;n++)t+=r[n];return t}function a(r,t){for(var n=0,e=0;e<r.length;e++)n+=r[e][t];return n}function u(r,t){return r>t?1:r<t?-1:r===t?0:NaN}function i(r,t,n,e){for(null==n&&(n=0),null==e&&(e=r.length);n<e;){var o=Math.floor((n+e)/2),a=u(r[o],t);if(a>0)e=o;else{if(!(a<0))return o+1;n=o+1}}return n}function f(r,t,n){if(r&&t){if(r.map&&r.map===c)return r.map(t,n);for(var e=[],o=0,a=r.length;o<a;o++)e.push(t.call(n,r[o],o,r));return e}}var l=Object.prototype.toString,s=Array.prototype,c=s.map;return{size:t,isArray:n,zeros:e,sum:o,sumOfColumn:a,ascending:u,bisect:i,map:f}}.call(t,n,t,r),!(void 0!==e&&(r.exports=e))},function(r,t,n){var e;e=function(r){var t=n(9);return function(r){var n=t(r);return n?Math.sqrt(n):n}}.call(t,n,t,r),!(void 0!==e&&(r.exports=e))},function(r,t,n){var e;e=function(r){function t(r){for(var t=-(1/0),n=0;n<r.length;n++)o(r[n])&&r[n]>t&&(t=r[n]);return t}var e=n(1),o=e.isNumber;return t}.call(t,n,t,r),!(void 0!==e&&(r.exports=e))},function(r,t,n){var e;e=function(r){function t(r){var t=r.length;return t?e(r)/r.length:0}var e=n(10);return t}.call(t,n,t,r),!(void 0!==e&&(r.exports=e))},function(r,t,n){var e;e=function(r){function t(r){for(var t=1/0,n=0;n<r.length;n++)o(r[n])&&r[n]<t&&(t=r[n]);return t}var e=n(1),o=e.isNumber;return t}.call(t,n,t,r),!(void 0!==e&&(r.exports=e))},function(r,t,n){var e;e=function(r){function t(r){var t=r.length;if(!t||t<2)return 0;if(r.length>=2){for(var n,e=a(r),u=0,i=0;i<r.length;i++)o(r[i])&&(n=r[i]-e,u+=n*n);return u/(r.length-1)}}var e=n(1),o=e.isNumber,a=n(7);return t}.call(t,n,t,r),!(void 0!==e&&(r.exports=e))},function(r,t,n){var e;e=function(r){function t(r){var t=r.length;if(!t)return 0;for(var n=0,e=0;e<t;e++)o(r[e])&&(n+=r[e]);return n}var e=n(1),o=e.isNumber;return t}.call(t,n,t,r),!(void 0!==e&&(r.exports=e))},function(r,t,n){var e;e=function(r){function t(r,t){for(var n,o,i,f,l=s(r),c=v(l[0],2),h=a(r,t),p=!0;p;){p=!1;for(var g=0;g<l[0];g++){n=1/0,o=-1;for(var M=0;M<t;M++)i=u(r[g],h[M]),i<n&&(n=i,o=M);c[g][0]!==o&&(p=!0),c[g][0]=o,c[g][1]=d(n,2)}for(var g=0;g<t;g++){f=[];for(var M=0;M<c.length;M++)c[M][0]===g&&f.push(r[M]);h[g]=e(f)}}var x={centroids:h,clusterAssigned:c};return x}function e(r){for(var t,n,e=s(r),o=[],a=0;a<e[1];a++){t=0;for(var u=0;u<e[0];u++)t+=r[u][a];n=t/e[0],o.push(n)}return o}function o(r,n,o){function a(){if(F<n){y=1/0;for(var r,e,o,a=0;a<x.length;a++){b=[],w=[];for(var u=0;u<g.length;u++)g[u][0]===a?b.push(l[u]):w.push(g[u][1]);N=t(b,2),A=c(N.clusterAssigned,1),q=h(w),A+q<y&&(y=q+A,r=a,e=N.centroids,o=N.clusterAssigned)}for(var u=0;u<o.length;u++)0===o[u][0]?o[u][0]=r:1===o[u][0]&&(o[u][0]=x.length);for(x[r]=e[0],x.push(e[1]),u=0,a=0;u<g.length&&a<o.length;u++)g[u][0]===r&&(g[u][0]=o[a][0],g[u][1]=o[a++][1]);for(var i=[],u=0;u<x.length;u++){i[u]=[];for(var a=0;a<g.length;a++)g[a][0]===u&&i[u].push(l[a])}P.clusterAssment=g,P.centroids=x,P.pointsInCluster=i,F++}else P.isEnd=!0;return P}if(!(n<2)){for(var i,l=f(r),p=s(l),g=v(p[0],2),M=e(l),x=[M],m=0;m<p[0];m++)i=u(l[m],M),g[m][1]=d(i,2);var y,b,w,N,A,q,F=1,P={isEnd:!1},E={next:a};if(o)return E;for(var P;!(P=E.next()).isEnd;);return P}}function a(r,t){for(var n,e,o,a=s(r),u=v(t,a[1]),i=0;i<a[1];i++){n=r[0][i],e=r[0][i];for(var f=1;f<a[0];f++)r[f][i]<n&&(n=r[f][i]),r[f][i]>e&&(e=r[f][i]);o=e-n;for(var f=0;f<t;f++)u[f][i]=n+o*Math.random()}return u}function u(r,t){if(!p(r)&&!p(t))return g(d(r-t,2));for(var n=0,e=0;e<r.length;e++)n+=d(r[e]-t[e],2);return g(n)}var i=n(2),f=i.dataPreprocess,l=n(4),s=l.size,c=l.sumOfColumn,h=l.sum,v=l.zeros,p=l.isArray,g=Math.sqrt,d=Math.pow;return{kMeans:t,hierarchicalKMeans:o}}.call(t,n,t,r),!(void 0!==e&&(r.exports=e))},function(r,t,n){var e;e=function(r){function t(r,t){t=null==t?g.squareRoot:g[t];for(var n=f(r),a=e(n),u=o(n),i=t(n,u,a),l=p(u,a,i),s=-Math.floor(Math.log(Math.abs(a-u)/i)/Math.LN10),d=h(+(Math.ceil(u/l)*l).toFixed(s),+(Math.floor(a/l)*l).toFixed(s),l,s),M=d.length,x=new Array(M+1),m=0;m<=M;m++)x[m]={},x[m].sample=[],x[m].x0=m>0?d[m-1]:d[m]-u===l?u:d[m]-l,x[m].x1=m<M?d[m]:a-d[m-1]===l?a:d[m-1]+l;for(var m=0;m<n.length;m++)u<=n[m]&&n[m]<=a&&x[v(d,n[m],0,M)].sample.push(n[m]);var r=c(x,function(r){return[+((r.x0+r.x1)/2).toFixed(s),r.sample.length]}),y=c(x,function(r){return[r.x0,r.x1,r.sample.length]});return{bins:x,data:r,customData:y}}var e=n(6),o=n(8),a=n(3),u=n(5),i=n(2),f=i.dataPreprocess,l=(i.getPrecision,n(4)),s=l.ascending,c=l.map,h=n(16),v=l.bisect,p=n(17),g={squareRoot:function(r){var t=Math.ceil(Math.sqrt(r.length));return t>50?50:t},scott:function(r,t,n){return Math.ceil((n-t)/(3.5*u(r)*Math.pow(r.length,-1/3)))},freedmanDiaconis:function(r,t,n){return r.sort(s),Math.ceil((n-t)/(2*(a(r,.75)-a(r,.25))*Math.pow(r.length,-1/3)))},sturges:function(r){return Math.ceil(Math.log(r.length)/Math.LN2)+1}};return t}.call(t,n,t,r),!(void 0!==e&&(r.exports=e))},function(r,t,n){var e;e=function(r){function t(r,t){for(var n=0;n<r.length-1;n++){for(var e=n,o=n+1;o<r.length-1;o++)Math.abs(r[n][o])>Math.abs(r[n][e])&&(e=o);for(var a=n;a<r.length;a++){var u=r[a][n];r[a][n]=r[a][e],r[a][e]=u}for(var i=n+1;i<r.length-1;i++)for(var f=r.length-1;f>=n;f--)r[f][i]-=r[f][n]/r[n][n]*r[n][i]}for(var l=new Array(t),s=r.length-1,o=r.length-2;o>=0;o--){for(var u=0,n=o+1;n<r.length-1;n++)u+=r[n][o]*l[n];l[o]=(r[s][o]-u)/r[o][o]}return l}var e=n(2),o=e.dataPreprocess,a={linear:function(r){for(var t=o(r),n=0,e=0,a=0,u=0,i=t.length,f=0;f<i;f++)n+=t[f][0],e+=t[f][1],a+=t[f][0]*t[f][1],u+=t[f][0]*t[f][0];for(var l=(i*a-n*e)/(i*u-n*n),s=e/i-l*n/i,c=[],h=0;h<t.length;h++){var v=[t[h][0],l*t[h][0]+s];c.push(v)}var p="y = "+Math.round(100*l)/100+"x + "+Math.round(100*s)/100;return{points:c,parameter:{gradient:l,intercept:s},expression:p}},linearThroughOrigin:function(r){for(var t=o(r),n=0,e=0,a=0;a<t.length;a++)n+=t[a][0]*t[a][0],e+=t[a][0]*t[a][1];for(var u=e/n,i=[],f=0;f<t.length;f++){var l=[t[f][0],t[f][0]*u];i.push(l)}var s="y = "+Math.round(100*u)/100+"x";return{points:i,parameter:{gradient:u},expression:s}},exponential:function(r){for(var t=o(r),n=0,e=0,a=0,u=0,i=0,f=0,l=0;l<t.length;l++)n+=t[l][0],e+=t[l][1],f+=t[l][0]*t[l][1],a+=t[l][0]*t[l][0]*t[l][1],u+=t[l][1]*Math.log(t[l][1]),i+=t[l][0]*t[l][1]*Math.log(t[l][1]);for(var s=e*a-f*f,c=Math.pow(Math.E,(a*u-f*i)/s),h=(e*i-f*u)/s,v=[],p=0;p<t.length;p++){var g=[t[p][0],c*Math.pow(Math.E,h*t[p][0])];v.push(g)}var d="y = "+Math.round(100*c)/100+"e^("+Math.round(100*h)/100+"x)";return{points:v,parameter:{coefficient:c,index:h},expression:d}},logarithmic:function(r){for(var t=o(r),n=0,e=0,a=0,u=0,i=0;i<t.length;i++)n+=Math.log(t[i][0]),e+=t[i][1]*Math.log(t[i][0]),a+=t[i][1],u+=Math.pow(Math.log(t[i][0]),2);for(var f=(i*e-a*n)/(i*u-n*n),l=(a-f*n)/i,s=[],c=0;c<t.length;c++){var h=[t[c][0],f*Math.log(t[c][0])+l];s.push(h)}var v="y = "+Math.round(100*l)/100+" + "+Math.round(100*f)/100+"ln(x)";return{points:s,parameter:{gradient:f,intercept:l},expression:v}},polynomial:function(r,n){var e=o(r);"undefined"==typeof n&&(n=2);for(var a=[],u=[],i=n+1,f=0;f<i;f++){for(var l=0,s=0;s<e.length;s++)l+=e[s][1]*Math.pow(e[s][0],f);u.push(l);for(var c=[],h=0;h<i;h++){for(var v=0,p=0;p<e.length;p++)v+=Math.pow(e[p][0],f+h);c.push(v)}a.push(c)}a.push(u);for(var g=t(a,i),d=[],f=0;f<e.length;f++){for(var M=0,s=0;s<g.length;s++)M+=g[s]*Math.pow(e[f][0],s);d.push([e[f][0],M])}for(var x="y = ",f=g.length-1;f>=0;f--)x+=f>1?Math.round(g[f]*Math.pow(10,f+1))/Math.pow(10,f+1)+"x^"+f+" + ":1===f?Math.round(100*g[f])/100+"x + ":Math.round(100*g[f])/100;return{points:d,parameter:g,expression:x}}},u=function(r,t,n){return a[r](t,n)};return u}.call(t,n,t,r),!(void 0!==e&&(r.exports=e))},function(r,t,n){var e;e=function(r){var t={};return t.max=n(6),t.deviation=n(5),t.mean=n(7),t.median=n(15),t.min=n(8),t.quantile=n(3),t.sampleVariance=n(9),t.sum=n(10),t}.call(t,n,t,r),!(void 0!==e&&(r.exports=e))},function(r,t,n){var e;e=function(r){function t(r){return e(r,.5)}var e=n(3);return t}.call(t,n,t,r),!(void 0!==e&&(r.exports=e))},function(r,t,n){var e;e=function(r){var t=n(2),e=t.getPrecision;return function(r,t,n,o){var a=arguments.length;a<2?(t=r,r=0,n=1):a<3?n=1:a<4?(n=+n,o=e(n)):o=+o;for(var u=Math.ceil(((t-r)/n).toFixed(o)),i=new Array(u+1),f=0;f<u+1;f++)i[f]=+(r+f*n).toFixed(o);return i}}.call(t,n,t,r),!(void 0!==e&&(r.exports=e))},function(r,t,n){var e;e=function(r){return function(r,t,n){var e=Math.abs(t-r)/n,o=Math.floor(Math.log(e)/Math.LN10),a=Math.pow(10,o),u=e/a;return u>=Math.sqrt(50)?a*=10:u>=Math.sqrt(10)?a*=5:u>=Math.sqrt(2)&&(a*=2),+(t>=r?a:-a).toFixed(-o)}}.call(t,n,t,r),!(void 0!==e&&(r.exports=e))}])});
!function(n,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define([],r):"object"==typeof exports?exports.ecStat=r():n.ecStat=r()}(this,function(){return function(n){function r(e){if(t[e])return t[e].exports;var o=t[e]={exports:{},id:e,loaded:!1};return n[e].call(o.exports,o,o.exports,r),o.loaded=!0,o.exports}var t={};return r.m=n,r.c=t,r.p="",r(0)}([function(n,r,t){var e;e=function(n){return{clustering:t(6),regression:t(8),statistics:t(15),histogram:t(7),transform:{regression:t(19),histogram:t(18),clustering:t(17)}}}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){function r(n){return n=null===n?NaN:+n,"number"==typeof n&&!isNaN(n)}function t(n){return isFinite(n)&&n===Math.round(n)}function e(n){if(0===n)return 0;var r=Math.floor(Math.log(n)/Math.LN10);return n/Math.pow(10,r)>=10&&r++,r}return{isNumber:r,isInteger:t,quantityExponent:e}}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){function r(n){for(var r=[];t(n);)r.push(n.length),n=n[0];return r}function t(n){return"[object Array]"===l.call(n)}function e(n,r){for(var t=[],e=0;e<n;e++){t[e]=[];for(var o=0;o<r;o++)t[e][o]=0}return t}function o(n){for(var r=0,t=0;t<n.length;t++)r+=n[t];return r}function i(n,r){for(var t=0,e=0;e<n.length;e++)t+=n[e][r];return t}function a(n,r){return n>r?1:n<r?-1:n===r?0:NaN}function u(n,r,t,e){for(null==t&&(t=0),null==e&&(e=n.length);t<e;){var o=Math.floor((t+e)/2),i=a(n[o],r);if(i>0)e=o;else{if(!(i<0))return o+1;t=o+1}}return t}function s(n,r,t){if(n&&r){if(n.map&&n.map===c)return n.map(r,t);for(var e=[],o=0,i=n.length;o<i;o++)e.push(r.call(t,n[o],o,n));return e}}var l=Object.prototype.toString,f=Array.prototype,c=f.map;return{size:r,isArray:t,zeros:e,sum:o,sumOfColumn:i,ascending:a,bisect:u,map:s}}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){function r(n,r){return"number"==typeof n?[n]:null==n?r:n}function e(n,r){function t(n){return!e||o.hasOwnProperty(n)}r=r||{};var e=r.dimensions,o={};if(null!=e)for(var i=0;i<e.length;i++)o[e[i]]=!0;var s=r.toOneDimensionArray?e?e[0]:0:null;if(!a(n))throw new Error("Invalid data type, you should input an array");var f=[],c=u(n);if(1===c.length)for(var i=0;i<c[0];i++){var v=n[i];l(v)&&f.push(v)}else if(2===c.length)for(var i=0;i<c[0];i++){for(var h=!0,v=n[i],p=0;p<c[1];p++)t(p)&&!l(v[p])&&(h=!1);h&&f.push(null!=s?v[s]:v)}return f}function o(n){var r=n.toString(),t=r.indexOf(".");return t<0?0:r.length-1-t}var i=t(2),a=i.isArray,u=i.size,s=t(1),l=s.isNumber;return{normalizeDimensions:r,dataPreprocess:e,getPrecision:o}}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){return function(n,r){var t=n.length;if(!t)return 0;if(r<=0||t<2)return n[0];if(r>=1)return n[t-1];var e=(t-1)*r,o=Math.floor(e),i=n[o],a=n[o+1];return i+(a-i)*(e-o)}}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){function r(n,r){function t(n,r){if(!n)throw new Error("Can not find dimension by "+r)}if(null!=r){var e=n.upstream;if(o.isArray(r)){for(var i=[],a=0;a<r.length;a++){var u=e.getDimensionInfo(r[a]);t(u,r[a]),i[a]=u.index}return i}var u=e.getDimensionInfo(r);return t(u,r),u.index}}function e(n){function r(n){if(i.isNumber(n))return{index:n};if(a.isObject(n)&&i.isNumber(n.index))return n;throw new Error("Illegle new dimensions config. Expect `{ name: string, index: number }`.")}if(o.isArray(n)){for(var t=[],e=[],u=0;u<n.length;u++){var s=r(n[u]);t.push(s.name),e.push(s.index)}return{name:t,index:e}}if(null!=n)return r(n)}var o=t(2),i=t(1),a=t(20);return{normalizeExistingDimensions:r,normalizeNewDimensions:e}}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){function r(n,r,t){for(var o,i,s,f,c=x(n.length,2),v=a(r,l(n,t.dimensions)),h=!0;h;){h=!1;for(var p=0;p<n.length;p++){o=1/0,i=-1;for(var d=0;d<r;d++)s=u(n[p],v[d],t),s<o&&(o=s,i=d);c[p][0]!==i&&(h=!0),c[p][0]=i,c[p][1]=o}for(var p=0;p<r;p++){f=[];for(var d=0;d<c.length;d++)c[d][0]===p&&f.push(n[d]);v[p]=e(f,t)}}var m={centroids:v,clusterAssigned:c};return m}function e(n,r){for(var t,e,o=[],i=0;i<r.dimensions.length;i++){var a=r.dimensions[i];t=0;for(var u=0;u<n.length;u++)t+=n[u][a];e=t/n.length,o.push(e)}return o}function o(n,t,o){function a(n,r){N[n][1]=r}function l(n){return N[n][1]}function f(){if(F<h){S=1/0;for(var n,t,e,o=0;o<O.length;o++){q=[],P=[];for(var i=0;i<E.length;i++)y(i)===o?q.push(E[i]):P.push(l(i));L=r(q,2,b),T=m(L.clusterAssigned,1),j=g(P),T+j<S&&(S=j+T,n=o,t=L.centroids,e=L.clusterAssigned)}for(var i=0;i<e.length;i++)0===e[i][0]?e[i][0]=n:1===e[i][0]&&(e[i][0]=O.length);O[n]=t[0],O.push(t[1]);for(var i=0,o=0;i<E.length&&o<e.length;i++)y(i)===n&&(d(i,e[o][0]),a(i,e[o++][1]));var u=[];if(!D){for(var i=0;i<O.length;i++){u[i]=[];for(var o=0;o<E.length;o++)y(o)===i&&u[i].push(E[o])}V.pointsInCluster=u}F++}else V.isEnd=!0}var v=(M(t)?{clusterCount:t,stepByStep:o}:t)||{clusterCount:2},h=v.clusterCount;if(!(h<2)){var p,d,y,b=s(n,v),D=b.outputType===w.SINGLE,E=c(n,{dimensions:b.dimensions}),N=x(E.length,2);if(D){p=[];var C=b.outputClusterIndexDimension;d=function(n,r){p[n][C]=r},y=function(n){return p[n][C]};for(var I=0;I<E.length;I++)p.push(E[I].slice()),a(I,0),d(I,0)}else d=function(n,r){N[n][0]=r},y=function(n){return N[n][0]};for(var A=e(E,b),O=[A],I=0;I<E.length;I++){var z=u(E[I],A,b);a(I,z)}var S,q,P,L,T,j,F=1,V={data:p,centroids:O,isEnd:!1};if(D||(V.clusterAssment=N),v.stepByStep)V.next=function(){return f(),i(V,b),V};else for(;f(),!V.isEnd;);return i(V,b),V}}function i(n,r){var t=r.outputCentroidDimensions;if(r.outputType===w.SINGLE&&null!=t)for(var e=n.data,o=n.centroids,i=0;i<e.length;i++)for(var a=e[i],u=a[r.outputClusterIndexDimension],s=o[u],l=Math.min(s.length,t.length),f=0;f<l;f++)a[t[f]]=s[f]}function a(n,r){for(var t=x(n,r.length),e=0;e<r.length;e++)for(var o=r[e],i=0;i<n;i++)t[i][e]=o.min+o.span*Math.random();return t}function u(n,r,t){for(var e=0,o=t.dimensions,i=t.rawExtents,a=0;a<o.length;a++){var u=i[a].span;if(u){var s=o[a],l=(n[s]-r[a])/u;e+=y(l,2)}}return e}function s(n,r){var t=d(n);if(t.length<1)throw new Error("The input data of clustering should be two-dimension array.");for(var e=t[1],o=[],i=0;i<e;i++)o.push(i);var a=v(r.dimensions,o),u=r.outputType||w.MULTIPLE,s=r.outputClusterIndexDimension;if(u===w.SINGLE&&!p.isNumber(s))throw new Error("outputClusterIndexDimension is required as a number.");var f=l(n,a);return{dimensions:a,rawExtents:f,outputType:u,outputClusterIndexDimension:s,outputCentroidDimensions:r.outputCentroidDimensions}}function l(n,r){for(var t=[],e=r.length,o=0;o<e;o++)t.push({min:1/0,max:-(1/0)});for(var o=0;o<n.length;o++)for(var i=n[o],a=0;a<e;a++){var u=t[a],s=i[r[a]];u.min>s&&(u.min=s),u.max<s&&(u.max=s)}for(var o=0;o<e;o++)t[o].span=t[o].max-t[o].min;return t}var f=t(3),c=f.dataPreprocess,v=f.normalizeDimensions,h=t(2),p=t(1),d=h.size,m=h.sumOfColumn,g=h.sum,x=h.zeros,p=t(1),M=p.isNumber,y=Math.pow,w={SINGLE:"single",MULTIPLE:"multiple"};return{OutputType:w,hierarchicalKMeans:o}}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){function r(n,r){for(var t="string"==typeof r?{method:r}:r||{},i=null==t.method?m.squareRoot:m[t.method],a=l(t.dimensions),u=s(n,{dimensions:a,toOneDimensionArray:!0}),f=e(u),c=o(u),g=i(u,c,f),x=d(c,f,g),M=x.step,y=x.toFixedPrecision,w=h(+(Math.ceil(c/M)*M).toFixed(y),+(Math.floor(f/M)*M).toFixed(y),M,y),b=w.length,D=new Array(b+1),E=0;E<=b;E++)D[E]={},D[E].sample=[],D[E].x0=E>0?w[E-1]:w[E]-c===M?c:w[E]-M,D[E].x1=E<b?w[E]:f-w[E-1]===M?f:w[E-1]+M;for(var E=0;E<u.length;E++)c<=u[E]&&u[E]<=f&&D[p(w,u[E],0,b)].sample.push(u[E]);var n=v(D,function(n){return[+((n.x0+n.x1)/2).toFixed(y),n.sample.length,n.x0,n.x1,n.x0+" - "+n.x1]}),N=v(D,function(n){return[n.x0,n.x1,n.sample.length]});return{bins:D,data:n,customData:N}}var e=t(10),o=t(12),i=t(4),a=t(9),u=t(3),s=u.dataPreprocess,l=u.normalizeDimensions,f=t(2),c=f.ascending,v=f.map,h=t(21),p=f.bisect,d=t(22),m={squareRoot:function(n){var r=Math.ceil(Math.sqrt(n.length));return r>50?50:r},scott:function(n,r,t){return Math.ceil((t-r)/(3.5*a(n)*Math.pow(n.length,-1/3)))},freedmanDiaconis:function(n,r,t){return n.sort(c),Math.ceil((t-r)/(2*(i(n,.75)-i(n,.25))*Math.pow(n.length,-1/3)))},sturges:function(n){return Math.ceil(Math.log(n.length)/Math.LN2)+1}};return r}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){function r(n,r){for(var t=0;t<n.length-1;t++){for(var e=t,o=t+1;o<n.length-1;o++)Math.abs(n[t][o])>Math.abs(n[t][e])&&(e=o);for(var i=t;i<n.length;i++){var a=n[i][t];n[i][t]=n[i][e],n[i][e]=a}for(var u=t+1;u<n.length-1;u++)for(var s=n.length-1;s>=t;s--)n[s][u]-=n[s][t]/n[t][t]*n[t][u]}for(var l=new Array(r),f=n.length-1,o=n.length-2;o>=0;o--){for(var a=0,t=o+1;t<n.length-1;t++)a+=n[t][o]*l[t];l[o]=(n[f][o]-a)/n[o][o]}return l}var e=t(3),o=e.dataPreprocess,i=e.normalizeDimensions,a={linear:function(n,r){for(var t=r.dimensions[0],e=r.dimensions[1],o=0,i=0,a=0,u=0,s=n.length,l=0;l<s;l++){var f=n[l];o+=f[t],i+=f[e],a+=f[t]*f[e],u+=f[t]*f[t]}for(var c=(s*a-o*i)/(s*u-o*o),v=i/s-c*o/s,h=[],p=0;p<n.length;p++){var f=n[p],d=f.slice();d[t]=f[t],d[e]=c*f[t]+v,h.push(d)}var m="y = "+Math.round(100*c)/100+"x + "+Math.round(100*v)/100;return{points:h,parameter:{gradient:c,intercept:v},expression:m}},linearThroughOrigin:function(n,r){for(var t=r.dimensions[0],e=r.dimensions[1],o=0,i=0,a=0;a<n.length;a++){var u=n[a];o+=u[t]*u[t],i+=u[t]*u[e]}for(var s=i/o,l=[],f=0;f<n.length;f++){var u=n[f],c=u.slice();c[t]=u[t],c[e]=u[t]*s,l.push(c)}var v="y = "+Math.round(100*s)/100+"x";return{points:l,parameter:{gradient:s},expression:v}},exponential:function(n,r){for(var t=r.dimensions[0],e=r.dimensions[1],o=0,i=0,a=0,u=0,s=0,l=0,f=0;f<n.length;f++){var c=n[f];o+=c[t],i+=c[e],l+=c[t]*c[e],a+=c[t]*c[t]*c[e],u+=c[e]*Math.log(c[e]),s+=c[t]*c[e]*Math.log(c[e])}for(var v=i*a-l*l,h=Math.pow(Math.E,(a*u-l*s)/v),p=(i*s-l*u)/v,d=[],m=0;m<n.length;m++){var c=n[m],g=c.slice();g[t]=c[t],g[e]=h*Math.pow(Math.E,p*c[t]),d.push(g)}var x="y = "+Math.round(100*h)/100+"e^("+Math.round(100*p)/100+"x)";return{points:d,parameter:{coefficient:h,index:p},expression:x}},logarithmic:function(n,r){for(var t=r.dimensions[0],e=r.dimensions[1],o=0,i=0,a=0,u=0,s=0;s<n.length;s++){var l=n[s];o+=Math.log(l[t]),i+=l[e]*Math.log(l[t]),a+=l[e],u+=Math.pow(Math.log(l[t]),2)}for(var f=(s*i-a*o)/(s*u-o*o),c=(a-f*o)/s,v=[],h=0;h<n.length;h++){var l=n[h],p=l.slice();p[t]=l[t],p[e]=f*Math.log(l[t])+c,v.push(p)}var d="y = "+Math.round(100*c)/100+" + "+Math.round(100*f)/100+"ln(x)";return{points:v,parameter:{gradient:f,intercept:c},expression:d}},polynomial:function(n,t){var e=t.dimensions[0],o=t.dimensions[1],i=t.order;null==i&&(i=2);for(var a=[],u=[],s=i+1,l=0;l<s;l++){for(var f=0,c=0;c<n.length;c++){var v=n[c];f+=v[o]*Math.pow(v[e],l)}u.push(f);for(var h=[],p=0;p<s;p++){for(var d=0,m=0;m<n.length;m++)d+=Math.pow(n[m][e],l+p);h.push(d)}a.push(h)}a.push(u);for(var g=r(a,s),x=[],l=0;l<n.length;l++){for(var M=0,v=n[l],c=0;c<g.length;c++)M+=g[c]*Math.pow(v[e],c);var y=v.slice();y[e]=v[e],y[o]=M,x.push(y)}for(var w="y = ",l=g.length-1;l>=0;l--)w+=l>1?Math.round(g[l]*Math.pow(10,l+1))/Math.pow(10,l+1)+"x^"+l+" + ":1===l?Math.round(100*g[l])/100+"x + ":Math.round(100*g[l])/100;return{points:x,parameter:g,expression:w}}},u=function(n,r,t){var e="number"==typeof t?{order:t}:t||{},u=i(e.dimensions,[0,1]),s=o(r,{dimensions:u}),l=a[n](s,{order:e.order,dimensions:u}),f=u[0];return l.points.sort(function(n,r){return n[f]-r[f]}),l};return u}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){var r=t(13);return function(n){var t=r(n);return t?Math.sqrt(t):t}}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){function r(n){for(var r=-(1/0),t=0;t<n.length;t++)o(n[t])&&n[t]>r&&(r=n[t]);return r}var e=t(1),o=e.isNumber;return r}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){function r(n){var r=n.length;return r?e(n)/n.length:0}var e=t(14);return r}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){function r(n){for(var r=1/0,t=0;t<n.length;t++)o(n[t])&&n[t]<r&&(r=n[t]);return r}var e=t(1),o=e.isNumber;return r}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){function r(n){var r=n.length;if(!r||r<2)return 0;if(n.length>=2){for(var t,e=i(n),a=0,u=0;u<n.length;u++)o(n[u])&&(t=n[u]-e,a+=t*t);return a/(n.length-1)}}var e=t(1),o=e.isNumber,i=t(11);return r}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){function r(n){var r=n.length;if(!r)return 0;for(var t=0,e=0;e<r;e++)o(n[e])&&(t+=n[e]);return t}var e=t(1),o=e.isNumber;return r}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){var r={};return r.max=t(10),r.deviation=t(9),r.mean=t(11),r.median=t(16),r.min=t(12),r.quantile=t(4),r.sampleVariance=t(13),r.sum=t(14),r}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){function r(n){return e(n,.5)}var e=t(4);return r}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){var r=t(6),e=t(1),o=t(5),i=e.isNumber;return{type:"ecStat:clustering",transform:function(n){var t=n.upstream,e=n.config||{},a=e.clusterCount;if(!i(a)||a<=0)throw new Error('config param "clusterCount" need to be specified as an interger greater than 1.');if(1===a)return[{},{data:[]}];var u=o.normalizeNewDimensions(e.outputClusterIndexDimension),s=o.normalizeNewDimensions(e.outputCentroidDimensions);if(null==u)throw new Error("outputClusterIndexDimension is required as a number.");for(var l=r.hierarchicalKMeans(t.cloneRawData(),{clusterCount:a,stepByStep:!1,dimensions:o.normalizeExistingDimensions(n,e.dimensions),outputType:r.OutputType.SINGLE,outputClusterIndexDimension:u.index,outputCentroidDimensions:(s||{}).index}),f=t.cloneAllDimensionInfo(),c=[],v=0;v<f.length;v++){var h=f[v];c.push(h.name)}if(c[u.index]=u.name,s)for(var v=0;v<s.index.length;v++)null!=s.name[v]&&(c[s.index[v]]=s.name[v]);return[{dimensions:c,data:l.data},{data:l.centroids}]}}}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){var r=t(7),e=t(5);return{type:"ecStat:histogram",transform:function(n){var t=n.upstream,o=n.config||{},i=r(t.cloneRawData(),{method:o.method,dimensions:e.normalizeExistingDimensions(n,o.dimensions)});return[{dimensions:["MeanOfV0V1","VCount","V0","V1","DisplayableName"],data:i.data},{data:i.customData}]}}}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){var r=t(8),e=t(5),o=2;return{type:"ecStat:regression",transform:function(n){var t=n.upstream,i=n.config||{},a=i.method||"linear",u=r(a,t.cloneRawData(),{order:i.order,dimensions:e.normalizeExistingDimensions(n,i.dimensions)}),s=u.points,l=i.formulaOn;null==l&&(l="end");var f;if("none"!==l){for(var c=0;c<s.length;c++)s[c][o]="start"===l&&0===c||"all"===l||"end"===l&&c===s.length-1?u.expression:"";f=t.cloneAllDimensionInfo(),f[o]={}}return[{dimensions:f,data:s}]}}}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){function r(n,r){if(Object.assign)Object.assign(n,r);else for(var t in r)r.hasOwnProperty(t)&&(n[t]=r[t]);return n}function t(n){const r=typeof n;return"function"===r||!!n&&"object"===r}return{extend:r,isObject:t}}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){var r=t(3),e=r.getPrecision;return function(n,r,t,o){var i=arguments.length;i<2?(r=n,n=0,t=1):i<3?t=1:i<4?(t=+t,o=e(t)):o=+o;for(var a=Math.ceil(((r-n)/t).toFixed(o)),u=new Array(a+1),s=0;s<a+1;s++)u[s]=+(n+s*t).toFixed(o);return u}}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))},function(n,r,t){var e;e=function(n){var r=t(1);return function(n,t,e){var o=Math.abs(t-n)/e,i=r.quantityExponent(o),a=Math.pow(10,i),u=o/a;u>=Math.sqrt(50)?a*=10:u>=Math.sqrt(10)?a*=5:u>=Math.sqrt(2)&&(a*=2);var s=i<0?-i:0,l=+(t>=n?a:-a).toFixed(s);return{step:l,toFixedPrecision:s}}}.call(r,t,r,n),!(void 0!==e&&(n.exports=e))}])});
{
"name": "echarts-stat",
"version": "1.1.1",
"version": "1.2.0",
"description": "a statistical tool for ECharts",

@@ -11,2 +11,6 @@ "main": "index.js",

},
"scripts": {
"build": "./node_modules/.bin/webpack",
"release": "./node_modules/.bin/webpack && ./node_modules/.bin/webpack -p"
},
"license": "BSD",

@@ -13,0 +17,0 @@ "repository": {

# ecStat
A statistical and data mining tool for [ECharts](https://github.com/ecomfe/echarts). You can use it to analyze data and then visualize the results with ECharts, or just use it to process data.
A statistical and data mining tool for [Apache ECharts (incubating)](https://github.com/apache/incubator-echarts). You can use it to analyze data and then visualize the results with ECharts, or just use it to process data.
It works both in node.js and in the browser.
*Read this in other languages: [English](README.md), [简体中文](README.zh-CN.md).*
## Installing

@@ -12,4 +14,4 @@

```sh
npm install echarts-stat
```
npm install echarts-stat
```

@@ -40,67 +42,107 @@ Otherwise, download this tool from [dist directory](https://github.com/ecomfe/echarts-stat/tree/master/dist):

```js
var bins = ecStat.histogram(data, binMethod);
```
* Used as echarts transform (since echarts 5.0)
```js
echarts.registerTransform(ecStat.transform.histogram);
```
```js
chart.setOption({
dataset: [{
source: data
}, {
type: 'ecStat:histogram',
config: config
}],
...
});
```
* Standalone
```js
var bins = ecStat.histogram(data, config);
// or
var bins = ecStat.histogram(data, method);
```
##### Parameter
* `data` - `Array<number>`. Data samples of numbers.
* `data` - `number[] | number[][]`. Data samples of numbers.
```js
// One-dimension array
var data = [8.6, 8.8, 10.5, 10.7, 10.8, 11.0, ... ];
```
or
```js
// Two-dimension array
var data = [[8.3, 143], [8.6, 214], ...];
```
```js
var data = [8.6, 8.8, 10.5, 10.7, 10.8, 11.0, ... ];
```
* `config` - `object`.
* `config.method` - `'squareRoot' | 'scott' | 'freedmanDiaconis' | 'sturges'`. Optional. Methods to calculate the number of bin. There is no "best" number of bin, and different bin size can reveal different feature of data.
* `binMethod` - `string`. There are four methods to calculate the number of bin, which are `squareRoot`, `scott`, `freedmanDiaconis`, and `sturges`. Of course, there is no "best" number of bin, and different bin size can reveal different feature of data.
* `squareRoot` - This is the default method, which is also used by Excel histogram. Returns the number of bin according to [Square-root choice](https://en.wikipedia.org/wiki/Histogram#Mathematical_definition):
```js
var bins = ecStat.histogram(data);
```
* `squareRoot` - This is the default method, which is also used by Excel histogram. Returns the number of bin according to [Square-root choice](https://en.wikipedia.org/wiki/Histogram#Mathematical_definition):
```js
var bins = ecStat.histogram(data);
```
* `scott` - Returns the number of bin according to [Scott's normal reference Rule](https://en.wikipedia.org/wiki/Histogram#Mathematical_definition):
```js
var bins = ecStat.histogram(data, 'scott');
```
* `scott` - Returns the number of bin according to [Scott's normal reference Rule](https://en.wikipedia.org/wiki/Histogram#Mathematical_definition):
```js
var bins = ecStat.histogram(data, 'scott');
```
* `freedmanDiaconis` - Returns the number of bin according to [The Freedman-Diaconis rule](https://en.wikipedia.org/wiki/Histogram#Mathematical_definition):
```js
var bins = ecStat.histogram(data, 'freedmanDiaconis');
```
* `freedmanDiaconis` - Returns the number of bin according to [The Freedman-Diaconis rule](https://en.wikipedia.org/wiki/Histogram#Mathematical_definition):
```js
var bins = ecStat.histogram(data, 'freedmanDiaconis');
```
* `sturges` - Returns the number of bin according to [Sturges' formula](https://en.wikipedia.org/wiki/Histogram#Mathematical_definition):
```js
var bins = ecStat.histogram(data, 'sturges');
```
* `sturges` - Returns the number of bin according to [Sturges' formula](https://en.wikipedia.org/wiki/Histogram#Mathematical_definition):
```js
var bins = ecStat.histogram(data, 'sturges');
```
* `config.dimensions` - `(number | string)`. Optional. Specify the dimensions of data that are used to regression calculation. By default `0`, which means the column 0 and 1 is used in the regression calculation. In echarts transform usage, both dimension name (`string`) and dimension index (`number`) can be specified. In standalone usage, only dimension index can be specified (not able to define dimension name).
##### Return Value
* `bins` - `Object`. Contain detailed messages of each bin and data used for [ECharts](https://github.com/ecomfe/echarts) to draw the histogram.
* `bins.bins` - `Array.<Object>`. An array of bins, where each bin is an object, containing three attributes:
* `x0` - `number`. The lower bound of the bin (inclusive).
* `x1` - `number`. The upper bound of the bin (exclusive).
* `sample` - `Array.<number>`. Containing the associated elements from the input data.
* `bins.data` - `Array.<Array.<number>>`. Used for bar chart to draw the histogram, each bin data is an array not only containing the mean value of `x0` and `x1`, but also the length of `sample`, which is the number of sample values in this bin.
* `bins.customData` - `Array.<Array<number>>`. Used for custom chart to draw the histogram, each custom data is an array not only containing the `x0` and `x1`, but also the length of `sample`, which is the number of sample values in this bin.
##### Return Value (only for standalone usage)
* Used as echarts transform (since echarts 5.0)
```js
dataset: [{
source: [...]
}, {
transform: 'ecStat:histogram'
// // The result data of this dataset is like:
// [
// // MeanOfV0V1, VCount, V0, V1, DisplayableName
// [ 10, 212 8, 12, '8 - 12'],
// ...
// ]
// // The rest of the input dimensions that other than
// // config.dimensions specified are kept in the output.
}]
```
* Standalone
* `result` - `object`. Contain detailed messages of each bin and data used for [ECharts](https://github.com/ecomfe/echarts) to draw the histogram.
* `result.bins` - `BinItem[]`. An array of bins, where each bin is an object (`BinItem`), containing three attributes:
* `x0` - `number`. The lower bound of the bin (inclusive).
* `x1` - `number`. The upper bound of the bin (exclusive).
* `sample` - `number[]`. Containing the associated elements from the input data.
* `result.data` - `[MeanOfV0V1, VCount, V0, V1, DisplayableName][]`. Used for bar chart to draw the histogram, where the length of `sample` is the number of sample values in this bin. For example:
```js
var bins.data = [
// MeanOfV0V1, VCount, V0, V1, DisplayableName
[ 10, 212, 8, 12, '8 - 12'],
...
];
// The rest of the input dimensions that other than
// config.dimensions specified are kept in the output.
```
* `result.customData` - `[V0, V1, VCount][]`. Used for custom chart to draw the histogram, where the length of `sample` is the number of sample values in this bin.
#### Examples
This example using ECharts custom chart to draw the histogram, which is the best type of chart we recommend.
[test/transform/histogram_bar.html](https://github.com/ecomfe/echarts-stat/blob/master/test/transform/histogram_bar.html)
```html
<script src='https://cdn.bootcss.com/echarts/3.4.0/echarts.js'></script>
<script src='./dist/ecStat.js'></script>
<script>
[test/standalone/histogram_bar.html](https://github.com/ecomfe/echarts-stat/blob/master/test/standalone/histogram_bar.html)
var bins = ecStat.histogram(data);
var option = {
...
series: [{
type: 'custom',
...
}],
...
}
</script>
```
![histogram](img/histogram.png)

@@ -116,51 +158,159 @@

#### Syntax
```
var result = ecStat.clustering.hierarchicalKMeans(data, clusterNumber, stepByStep);
```
##### Parameter
* `data` - `Array.<Array.<number>>`. Two-dimensional numeric array, each data point can have more than two numeric attributes in the original data set. In the following example, `data[0]` is called `data point` and `data[0][1]` is one of the numeric attributes of `data[0]`.
```js
var data = [
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
...
];
```
* `clusterNumer` - `number`. The number of clusters generated. **Note that it has to be greater than 1.**
* `stepByStep` - `boolean`. Control whether doing the clustering step by step
* Used as echarts transform (since echarts 5.0)
```js
echarts.registerTransform(ecStat.transform.clustering);
```
```js
chart.setOption({
dataset: [{
source: data
}, {
type: 'ecStat:clustering',
config: config
}],
...
});
```
* Standalone
```js
var result = ecStat.clustering.hierarchicalKMeans(data, config);
// or
var result = ecStat.clustering.hierarchicalKMeans(data, clusterCount, stepByStep);
```
##### Return Value
##### Parameter
* `result` - `Object`. Including the centroids, clusterAssment, and pointsInCluster. For Example:
* `data` - `number[][]`. Two-dimensional numeric array, each data point can have more than two numeric attributes in the original data set. In the following example, `data[0]` is called `data point` and `data[0][1]` is one of the numeric attributes of `data[0]`.
```js
result.centroids = [
```js
var data = [
[232, 4.21, 51, 0.323, 19],
[321, 1.62, 18, 0.139, 10],
[551, 11.21, 13, 0.641, 15],
...
];
```
[-0.460, -2.778],
[2.934, 3.128],
...
];
* `config` - `object`.
* `config.clusterCount` - `number`. Mandatory. The number of clusters generated. **Note that it must be greater than 1.**
* `config.dimensions` - `(number | string)[]`. Optional. Specify which dimensions (columns) of data will be used to clustering calculation. The other columns will also be kept in the output data. By default all of the columns of the data will be used as dimensions. In echarts transform usage, both dimension name (`string`) and dimension index (`number`) can be specified. In standalone usage, only dimension index can be specified (not able to define dimension name).
* `config.stepByStep` - `boolean`. Optional. Control whether doing the clustering step by step. By default `false`.
* `config.outputType` - `'single' | 'multiple'`. Optional. Specify the format of the output. In "standalone" usage, it is by default `'multiple'`. In "transform" usage, it can not be specified, always be `'single'`.
* `config.outputClusterIndexDimension` - `(number | {index: number, name?: string})`. Mandatory. It only works in `config.outputType: 'single'`. In this mode, the cluster index will be written to that dimension index of the output data. If be a `number`, it means dimension index. Dimension index is mandatory, while dimension name is optional, which only enables the downstream refer this dimension by name.
* `config.outputCentroidDimensions` - `(number | {index: number, name?: string})[]` Optional. It only works in `config.outputType: 'single'`. If specify, the cluster centroid will be written to those dimensions of the result data. By default the centroids will not be written to the result data. If be a `number`, it means dimension index. Dimension index is mandatory, while dimension name is optional, which only enables the downstream refer this dimension by name.
// Indicate which cluster each data point belonging to, and the distance to cluster centroids
result.clusterAssment = [
##### Return Value
[1, 0.145],
[2, 0.680],
[0, 1.022],
...
];
For example, the input data is:
```js
var data = [
// dimensions:
// 0 1 2 3 4
[ 232, 4.21, 51, 0.323, 'xxx'],
[ 321, 1.62, 18, 0.139, 'xzx'],
[ 551, 11.21, 13, 0.641, 'yzy'],
...
];
```
And we specify the `config` as:
```js
config = {
dimensions: [2, 3],
outputClusterIndexDimension: 5
}
```
The result will be:
// Concrete data point in each cluster
result.pointsInCluster = [
[
[0.335, -3.376],
[-0.994, -0.884],
...
],
...
];
```
* Used as echarts transform (since echarts 5.0)
```js
dataset: [{
source: [ ... ],
}, {
transform: 'ecStat:clustering',
config: {
clusterCount: 6,
outputClusterIndexDimension: 5,
outputCentroidDimensions: [6, 7]
}
// The result data of this dataset will be:
// [
// // dim2, dim3 are used in clustering.
// // All of the input data are kept in the output.
// // dim5 is the output cluster index.
// // dim6 is the output distance value.
// // dimensions:
// // 0 1 2 3 4 5 6 7
// [ 232, 4.21, 51, 0.323, 'xxx', 0, 14, 0.145 ],
// [ 321, 1.62, 18, 0.139, 'xzx', 2, 24, 0.321 ],
// [ 551, 11.21, 13, 0.641, 'yzy', 0, 14, 0.145 ],
// ...
// ]
}, {
fromDatasetIndex: 1,
fromTransformResult: 1
// The result data of this dataset will be:
// centroids: [
// // center of cluster0
// [14, 0.145],
// // center of cluster1
// [24, 0.321],
// ...
// ]
}]
```
* Standalone
* `outputType: 'single'`:
* `result` - `object`. For example:
```js
result = {
data: [
// dim2, dim3 are used in clustering.
// All of the input data are kept in the output.
// dim5 is the output cluster index.
// dim6 is the output distance value.
// dimensions:
// 0 1 2 3 4 5 6
[ 232, 4.21, 51, 0.323, 'xxx', 0, 89 ],
[ 321, 1.62, 18, 0.139, 'xzx', 2, 23 ],
[ 551, 11.21, 13, 0.641, 'yzy', 0, ?? ],
...
],
centroids: [
// center of cluster0
[14, 0.145],
// center of cluster1
[24, 0.321],
...
]
}
```
* `outputType: 'multiple'`:
* `result` - `object`. Including the centroids, and pointsInCluster. For example:
```js
result = {
pointsInCluster: [
// points in cluster0
[
[ 232, 4.21, 51, 0.323, 'xxx' ],
[ 551, 11.21, 13, 0.641, 'yzy' ],
...
],
// points in cluster1
[
[ 321, 1.62, 18, 0.139, 'xzx' ],
...
],
...
],
centroids: [
// center of cluster0
[14, 0.145],
// center of cluster1
[24, 0.321],
...
]
};
```

@@ -175,13 +325,6 @@ #### Examples

```html
<script src='https://cdn.bootcss.com/echarts/3.4.0/echarts.js'></script>
<script src='./dist/ecStat.js'></script>
<script>
[test/transform/clustering_bikmeans.html](https://github.com/ecomfe/echarts-stat/blob/master/test/transform/clustering_bikmeans.html)
var clusterNumber = 3;
var result = ecStat.clustering.hierarchicalKMeans(data, clusterNumber, false);
[test/standalone/clustering_bikmeans.html](https://github.com/ecomfe/echarts-stat/blob/master/test/standalone/clustering_bikmeans.html)
</script>
```
![static clustering](img/static-clustering.png)

@@ -193,13 +336,4 @@

```html
<script src='https://cdn.bootcss.com/echarts/3.4.0/echarts.js'></script>
<script src='./dist/ecStat.js'></script>
<script>
[test/standalone/clustering_animation.html](https://github.com/ecomfe/echarts-stat/blob/master/test/standalone/clustering_animation.html)
var clusterNumber = 6;
var result = ecStat.clustering.hierarchicalKMeans(data, clusterNumber, true);
</script>
```
![dynamic clustering](http://g.recordit.co/DTTS8d0D4O.gif)

@@ -215,39 +349,84 @@

#### Syntax
```
var myRegression = ecStat.regression(regressionType, data, order);
```
##### Parameters
* `regressionType` - `string`. There are four types of regression, whice are `'linear'`, `'exponential'`, `'logarithmic'`, `'polynomial'`.
* `data` - `Array.<Array.<number>>`. Two-dimensional numeric array, Each data object should have two numeric attributes in the original data set. For Example:
* Used as echarts transform (since echarts 5.0)
```js
echarts.registerTransform(ecStat.transform.regression);
```
```js
chart.setOption({
dataset: [{
source: data
}, {
type: 'ecStat:regression',
config: {
method: regressionType,
...opt
}
}],
...
});
```
* Standalone
```js
var myRegression = ecStat.regression(regressionType, data, opt);
// or
var myRegression = ecStat.regression('polynomial', data, order);
```
```js
var data = [
##### Parameters
[1, 2],
[3, 5],
...
];
```
* `order` - `number`. The order of polynomial. If you choose other types of regression, you can ignore it.
* `regressionType` - `string`. Mandatory. There are four types of regression, which are `'linear'`, `'exponential'`, `'logarithmic'`, `'polynomial'`.
* `data` - `number[][]`. Two-dimensional numeric array, Each data object should have two numeric attributes in the original data set. For Example:
```js
var data = [
[1, 2],
[3, 5],
...
];
```
* `opt` - `object`.
* `opt.dimensions` - `(number | string)[] | (number | string)`. Optional. Specify the dimensions of data that are used to regression calculation. By default `[0, 1]`, which means the column 0 and 1 is used in the regression calculation. In echarts transform usage, both dimension name (`string`) and dimension index (`number`) can be specified. In standalone usage, only dimension index can be specified (not able to define dimension name).
* `opt.order` - `number`. Optional. By default `2`. The order of polynomial. If you choose other types of regression, you can ignore it.
##### Return Value
##### Return Value (only for standalone usage)
* `myRegression` - `Object`. Including points, parameter, and expression. For Example:
* Used as echarts transform (since echarts 5.0)
```js
dataset: [{
source: [...]
}, {
transform: 'ecStat:regression',
// // The result of this dataset is like:
// [
// // ValueOnX, ValueOnY
// [ 23, 51 ],
// [ 24, 62 ],
// ...
// ]
// // The rest of the input dimensions that other than
// // config.dimensions specified are kept in the output.
}]
```
* Standalone
* `myRegression` - `object`. Including points, parameter, and expression. For Example:
```js
myRegression.points = [
[1, 2],
[3, 4],
...
];
```js
myRegression.points = [
// ValueOnX, ValueOnY
[ 23, 51 ],
[ 24, 62 ],
...
];
// The rest of the input dimensions that other than
// config.dimensions specified are kept in the output.
// This is the parameter of linear regression, for other types, it shoule be a little different
myRegression.parameter = {
gradient: 1.695,
intercept: 3.008
};
// This is the parameter of linear regression,
// for other types, it should be a little different
myRegression.parameter = {
gradient: 1.695,
intercept: 3.008
};
myRegression.expression = 'y = 1.7x + 3.01';
```
myRegression.expression = 'y = 1.7x + 3.01';
```

@@ -260,12 +439,6 @@ #### Examples

```html
<script src='https://cdn.bootcss.com/echarts/3.4.0/echarts.js'></script>
<script src='./dist/ecStat.js'></script>
<script>
[test/transform/regression_linear.html](https://github.com/ecomfe/echarts-stat/blob/master/test/transform/regression_linear.html)
var myRegression = ecStat.regression('linear', data);
[test/standalone/regression_linear.html](https://github.com/ecomfe/echarts-stat/blob/master/test/standalone/regression_linear.html)
</script>
```
![linear regression](img/linear.png)

@@ -277,12 +450,6 @@

```html
<script src='https://cdn.bootcss.com/echarts/3.4.0/echarts.js'></script>
<script src='./dist/ecStat.js'></script>
<script>
[test/transform/regression_exponential.html](https://github.com/ecomfe/echarts-stat/blob/master/test/transform/regression_exponential.html)
var myRegression = ecStat.regression('exponential', data);
[test/standalone/regression_exponential.html](https://github.com/ecomfe/echarts-stat/blob/master/test/standalone/regression_exponential.html)
</script>
```
![exponential regression](img/exponential.png)

@@ -294,12 +461,6 @@

```html
<script src='https://cdn.bootcss.com/echarts/3.4.0/echarts.js'></script>
<script src='./dist/ecStat.js'></script>
<script>
[test/transform/regression_logarithmic.html](https://github.com/ecomfe/echarts-stat/blob/master/test/transform/regression_logarithmic.html)
var myRegression = ecStat.regression('logarithmic', data);
[test/standalone/regression_logarithmic.html](https://github.com/ecomfe/echarts-stat/blob/master/test/standalone/regression_logarithmic.html)
</script>
```
![logarithmic regression](img/logarithmic.png)

@@ -311,12 +472,6 @@

```html
<script src='https://cdn.bootcss.com/echarts/3.4.0/echarts.js'></script>
<script src='./dist/ecStat.js'></script>
<script>
[test/transform/regression_polynomial.html](https://github.com/ecomfe/echarts-stat/blob/master/test/transform/regression_polynomial.html)
var myRegression = ecStat.regression('polynomial', data, 3);
[test/standalone/regression_polynomial.html](https://github.com/ecomfe/echarts-stat/blob/master/test/standalone/regression_polynomial.html)
</script>
```
![polynomial regression](img/polynomial.png)

@@ -335,3 +490,3 @@

##### Syntax
```
```js
var sampleDeviation = ecStat.statistics.deviation(dataList);

@@ -341,3 +496,3 @@ ```

* `dataList` : `Array.<number>`
* `dataList` : `number[]`

@@ -352,3 +507,3 @@ ##### Return Value

##### Syntax
```
```js
var varianceValue = ecStat.statistics.sampleVariance(dataList);

@@ -358,7 +513,7 @@ ```

* `dataList` : `Array.<number>`
* `dataList` : `number[]`
##### Return Value
* `varianceValue`: `number`. Return the variance of the numeric array *dataList*. If the *dataList* is empty or the length less than 2, return 0.
* `varianceValue`: `number`. Return the variance of the numeric array *dataList*. If the *dataList* is empty or the length less than 2, return 0.

@@ -369,3 +524,3 @@

##### Syntax
```
```js
var quantileValue = ecStat.statistics.quantile(dataList, p);

@@ -375,3 +530,3 @@ ```

* `dataList` : `Array.<number>`. Sorted array of numbers.
* `dataList` : `number[]`. Sorted array of numbers.
* `p`: `number`. where 0 =< *p* <= 1. For example, the first quartile at p = 0.25, the seconed quartile at p = 0.5(same as the median), and the third quartile at p = 0.75.

@@ -381,3 +536,3 @@

* `quantileValue`: `number`. Return the *p*-quantile of the sorted array of numbers. If p <= 0 or the length of *dataList* less than 2, return the first element of the sorted array; if p >= 1, return the last element of the sorted array; If *dataList* is empty, return 0.
* `quantileValue`: `number`. Return the quantile of the sorted array of numbers. If p <= 0 or the length of *dataList* less than 2, return the first element of the sorted array *dataList*; if p >= 1, return the last element of the sorted array *dataList*; If *dataList* is empty, return 0.

@@ -388,3 +543,3 @@

##### Syntax
```
```js
var maxValue = ecStat.statistics.max(dataList);

@@ -394,3 +549,3 @@ ```

* `dataList` : `Array.<number>`
* `dataList` : `number[]`

@@ -405,3 +560,3 @@ ##### Return Value

##### Syntax
```
```js
var minValue = ecStat.statistics.min(dataList);

@@ -411,3 +566,3 @@ ```

* `dataList` : `Array.<number>`
* `dataList` : `number[]`

@@ -422,3 +577,3 @@ ##### Return Value

##### Syntax
```
```js
var meanValue = ecStat.statistics.mean(dataList);

@@ -428,3 +583,3 @@ ```

* `dataList` : `Array.<number>`
* `dataList` : `number[]`

@@ -439,3 +594,3 @@ ##### Return Value

##### Syntax
```
```js
var medianValue = ecStat.statistics.median(dataList);

@@ -445,3 +600,3 @@ ```

* `dataList` : `Array.<number>`. Sorted array of numbers
* `dataList` : `number[]`. Sorted array of numbers

@@ -456,3 +611,3 @@ ##### Return Value

##### Syntax
```
```js
var sumValue = ecStat.statistics.sum(dataList);

@@ -462,3 +617,3 @@ ```

* `dataList` : `Array.<number>`
* `dataList` : `number[]`

@@ -469,3 +624,1 @@ ##### Return Value

# ecStat
ecStat 是 [ECharts](https://github.com/ecomfe/echarts) 的统计和数据挖掘工具。你可以把它当作一个工具库直接用来分析数据;你也可以将其与 ECharts 结合使用,用 ECharts 可视化数据分析的结果。
ecStat 是 [Apache ECharts (incubating)](https://github.com/apache/incubator-echarts) 的统计和数据挖掘工具。你可以把它当作一个工具库直接用来分析数据;你也可以将其与 ECharts 结合使用,用 ECharts 可视化数据分析的结果。
同时支持 Node 和浏览器中使用。
*其他语言版本: [English](README.md), [简体中文](README.zh-CN.md).*
## 安装

@@ -39,80 +41,109 @@

```js
var bins = ecStat.histogram(data, binMethod);
```
* 作为 echarts transform 使用(echarts 5.0 开始支持)
```js
echarts.registerTransform(ecStat.transform.histogram);
```
```js
chart.setOption({
dataset: [{
source: data
}, {
type: 'ecStat:histogram',
config: config
}],
...
});
```
* 独立使用
```js
var bins = ecStat.histogram(data, config);
```
##### 参数说明
* `data` - `Array<number>`. 数值样本.
* `data` - `number[] | number[][]`. 数值样本.
```js
// 一维数组
var data = [8.6, 8.8, 10.5, 10.7, 10.8, 11.0, ... ];
```
or
```js
// 二维数组
var data = [[8.3, 143], [8.6, 214], ...];
```
```js
var data = [8.6, 8.8, 10.5, 10.7, 10.8, 11.0, ... ];
```
* `config` - `object`.
* `method` - `string`. 可选参数。直方图提供了四种计算小区间间隔个数的方法,分别是 `squareRoot`, `scott`, `freedmanDiaconis` 和 `sturges`。这里的每个小区间间隔又称为 `bin`,所有的小区间间隔组成的数组称为 `bins`。当然,对于一个直方图来说,没有所谓的最佳区间间隔个数,不同的区间间隔大小会揭示数据样本不同的数值特性。
* `binMethod` - `string`. 直方图提供了四种计算小区间间隔个数的方法,分别是 `squareRoot`, `scott`, `freedmanDiaconis` 和 `sturges`。这里的每个小区间间隔又称为 `bin`,所有的小区间间隔组成的数组称为 `bins`。当然,对于一个直方图来说,没有所谓的最佳区间间隔个数,不同的区间间隔大小会揭示数据样本不同的数值特性。
* `squareRoot` - 默认方法,Excel 的直方图中也是使用这个方法计算 `bins`。依照 [Square-root choice](https://en.wikipedia.org/wiki/Histogram#Mathematical_definition) 返回 bin 的个数:
```js
var bins = ecStat.histogram(data);
```
* `squareRoot` - 默认方法,Excel 的直方图中也是使用这个方法计算 `bins`。依照 [Square-root choice](https://en.wikipedia.org/wiki/Histogram#Mathematical_definition) 返回 bin 的个数:
```js
var bins = ecStat.histogram(data);
```
* `scott` - 依照 [Scott's normal reference Rule](https://en.wikipedia.org/wiki/Histogram#Mathematical_definition) 返回 bin 的个数:
```js
var bins = ecStat.histogram(data, 'scott');
```
* `scott` - 依照 [Scott's normal reference Rule](https://en.wikipedia.org/wiki/Histogram#Mathematical_definition) 返回 bin 的个数:
```js
var bins = ecStat.histogram(data, 'scott');
```
* `freedmanDiaconis` - 依照 [The Freedman-Diaconis rule](https://en.wikipedia.org/wiki/Histogram#Mathematical_definition) 返回 bin 的个数:
```js
var bins = ecStat.histogram(data, 'freedmanDiaconis');
```
* `freedmanDiaconis` - 依照 [The Freedman-Diaconis rule](https://en.wikipedia.org/wiki/Histogram#Mathematical_definition) 返回 bin 的个数:
```js
var bins = ecStat.histogram(data, 'freedmanDiaconis');
```
* `sturges` - 依照 [Sturges' formula](https://en.wikipedia.org/wiki/Histogram#Mathematical_definition) 返回 bin 的个数:
```js
var bins = ecStat.histogram(data, 'sturges');
```
* `sturges` - 依照 [Sturges' formula](https://en.wikipedia.org/wiki/Histogram#Mathematical_definition) 返回 bin 的个数:
```js
var bins = ecStat.histogram(data, 'sturges');
```
* `config.dimensions` - `(number | string)`. 可选参数。指定数据的哪些维度会被用于回归计算。默认为 `0`。在“echarts transform”模式下,维度名(`string`)和维度序数(`number`)都可被指定。在“独立使用”模式下,只有维度序数可被指定(因为此模式下并没有支持定义维度名)。
##### 返回值说明
* `bins` - `Object`. 返回值包含了每一个 bin 的详细信息,以及用 [ECharts](https://github.com/ecomfe/echarts) 绘制直方图所需要的数据信息。
* `bins.bins` - `Array.<Object>`. 包含所有小区间间隔的数组,其中每个区间间隔是一个对象,包含如下三个属性:
* `x0` - `number`. 区间间隔的下界 (包含)。
* `x1` - `number`. 区间间隔的上界 (不包含)。
* `sample` - `Array.<number>`. 落入该区间间隔的原始输入样本数据。
* `bins.data` - `Array.<Array.<number>>`. 用 ECharts 柱状图绘制直方图所需要的数据信息。这是一个二维数据,其中每个数据项是一个一维数组。该一维数组包含了 x0 和 x1 的均值,以及上述 sample 数组的长度,示例如下:
```js
var bins.data = [
[mean1, len1],
[mean2, len2],
...
];
```
* `bins.customData` - `Array.<Array<number>>`. 用 ECharts 自定义图表绘制直方图所需要的数据信息。这是一个二维数据,其中每个数据项是一个一维数组。该一维数组包含了 x0 和 x1,以及上述 sample 数组的长度,示例如下:
```js
var bins.customData = [
[x0, x1, len1],
...
];
```
* 作为 echarts transform 使用(echarts 5.0 开始支持)
```js
dataset: [{
source: [...]
}, {
transform: 'ecStat:histogram'
// // 本 dataset 中得到的结果数据如:
// [
// // MeanOfV0V1, VCount, V0, V1, DisplayableName
// [ 10, 212, 8, 12, '8 - 12'],
// ...
// ]
// // config.dimensions 之外的其他维度的数据
// // 也会保留在结果中。
}]
```
* 独立使用
* `bins` - `object`. 返回值包含了每一个 bin 的详细信息,以及用 [ECharts](https://github.com/ecomfe/echarts) 绘制直方图所需要的数据信息。
* `bins.bins` - `BinItem[]`. 包含所有小区间间隔的数组,其中每个区间间隔是一个对象 (`BinItem`),包含如下三个属性:
* `x0` - `number`. 区间间隔的下界 (包含)。
* `x1` - `number`. 区间间隔的上界 (不包含)。
* `sample` - `number[]`. 落入该区间间隔的原始输入样本数据。
* `bins.data` - `[MeanOfV0V1, VCount, V0, V1, DisplayableName][]`. 用 ECharts 柱状图绘制直方图所需要的数据信息。这是一个二维数据,其中每个数据项是一个一维数组。该一维数组包含了 x0 和 x1 的均值,以及上述 sample 数组的长度,示例如下:
```js
var bins.data = [
// MeanOfV0V1, VCount, V0, V1, DisplayableName
[ 10, 212, 8, 12, '8 - 12'],
...
];
// config.dimensions 之外的其他维度的数据
// 也会保留在结果中。
```
* `bins.customData` - `[V0, V1, VCount][]`. 用 ECharts 自定义图表绘制直方图所需要的数据信息。这是一个二维数据,其中每个数据项是一个一维数组。该一维数组包含了 x0 和 x1,以及上述 sample 数组的长度,示例如下:
```js
var bins.customData = [
[x0_0, x1_0, len_0],
...
];
```
#### 实例
这个示例使用 ECharts 自定义图表绘制直方图,相较于柱状图我们更推荐使用自定义图表绘制直方图。
[test/transform/histogram_bar.html](https://github.com/ecomfe/echarts-stat/blob/master/test/transform/histogram_bar.html)
[test/standalone/histogram_bar.html](https://github.com/ecomfe/echarts-stat/blob/master/test/standalone/histogram_bar.html)
```html
<script src='https://cdn.bootcss.com/echarts/3.4.0/echarts.js'></script>
<script src='./dist/ecStat.js'></script>
<script>
var bins = ecStat.histogram(data);
var option = {
...
series: [{
type: 'custom',
...
}],
...
}
</script>
```
![histogram](img/histogram.png)

@@ -128,51 +159,159 @@

#### 调用方式
```
var result = ecStat.clustering.hierarchicalKMeans(data, clusterNumber, stepByStep);
```
##### 参数说明
* `data` - `Array.<Array.<number>>`. 这是一个二维数组,其中每个数据对象是具有多个数值属性的一维数组。如下,`data[0]` 就是一个数据对象,`data[0][1]` 是该数据对象的一个数值属性。
```js
var data = [
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
...
];
```
* `clusterNumer` - `number`. 要生成的数据簇的个数。 **注意,该数值必须大于 1。**
* `stepByStep` - `boolean`. 该参数主要用于可视化聚类算法每一步的分割过程,即动态地展示数据簇如何从 2 个到 3 个,4 个, .... 。
* 作为 echarts transform 使用(echarts 5.0 开始支持)
```js
echarts.registerTransform(ecStat.transform.clustering);
```
```js
chart.setOption({
dataset: [{
source: data
}, {
type: 'ecStat:clustering',
config: config
}],
...
});
```
* 独立使用
```js
var result = ecStat.clustering.hierarchicalKMeans(data, config);
// or
var result = ecStat.clustering.hierarchicalKMeans(data, clusterCount, stepByStep);
```
##### 返回值说明
##### 参数说明
* `result` - `Object`. 包含每个数据簇的中心点 centroids,聚类的评估结果 clusterAssment,以及每个数据簇所包含的原始数据对象 pointsInCluster。如下:
* `data` - `number[][]`. 这是一个二维数组,其中每个数据对象是具有多个数值属性的一维数组。如下,`data[0]` 就是一个数据对象,`data[0][1]` 是该数据对象的一个数值属性。
```js
var data = [
[232, 4.21, 51, 0.323, 19],
[321, 1.62, 18, 0.139, 10],
[551, 11.21, 13, 0.641, 15],
...
];
```
* `config` - `object`.
* `config.clusterCount` - `number`. 必填参数。要生成的数据簇的个数。 **注意,该数值必须大于 1。**
* `config.dimensions` - `(number | string)[]`. 可选参数。指定哪些维度(即,列)要被用于聚类的计算。没有被用于计算的其他维度的值也会被拷贝到结果中。默认所有维度都会被用用于计算。在“echarts transform”模式下,维度名(`string`)和维度序数(`number`)都可被指定。在“独立使用”模式下,只有维度序数可被指定(因为此模式下并没有支持定义维度名)。
* `config.stepByStep` - `boolean`. 可选参数。该参数主要用于可视化聚类算法每一步的分割过程,即动态地展示数据簇如何从 2 个到 3 个,4 个, .... 。默认为 `false`。
* `config.outputType` - `'single' | 'multiple'`. 可选参数。指定输出格式。在“独立使用”中,它默认为`'multiple'`。在“transform”中,它不能被指定,总为`'single'`模式。
* `config.outputClusterIndexDimension` - `(number | {index: number, name?: string})`. 必填参数。簇的索引(clusterIndex)将被写入这列。此设定只在 `config.outputType: 'single'` 时生效。如果只给一个 `number`,则表示 dimension index 。 dimension index 是必须给出的,但是 dimension name 是可选的,只用于后续的 dataset 能用 name 来引用。
* `config.outputCentroidDimensions` - `(number | {index: number, name?: string})` 可选参数。此设定只在 `config.outputType: 'single'` 时生效。如果指定,会把每蔟的中心写入 `result.data` 指定的维度中。默认每蔟的中心不会被写入 `result.data` 中。如果只给一个 `number`,则表示 dimension index 。 dimension index 是必须给出的,但是 dimension name 是可选的,只用于后续的 dataset 能用 name 来引用。
```js
result.centroids = [
[-0.460, -2.778],
[2.934, 3.128],
...
];
##### 返回值说明
// indicate which cluster each data point belonging to, and the distance to cluster centroids
result.clusterAssment = [
例如,输入数据是:
```js
var data = [
// dimensions:
// 0 1 2 3 4
[ 232, 4.21, 51, 0.323, 'xxx'],
[ 321, 1.62, 18, 0.139, 'xzx'],
[ 551, 11.21, 13, 0.641, 'yzy'],
...
];
```
然后我们指定的 `config` 是:
```js
config = {
dimensions: [2, 3],
outputClusterIndexDimension: 5
}
```
则结果是:
[1, 0.145],
[2, 0.680],
[0, 1.022],
...
];
// concrete data point in each cluster
result.pointsInCluster = [
[
[0.335, -3.376],
[-0.994, -0.884],
...
],
...
];
```
* 作为 echarts transform 使用(echarts 5.0 开始支持)
```js
dataset: [{
source: [ ... ],
}, {
transform: 'ecStat:clustering',
config: {
clusterCount: 6,
outputClusterIndexDimension: 5,
outputCentroidDimensions: [6, 7]
}
// 本 dataset 得到的结果数据是例如:
// [
// // dim2, dim3 被用于聚类计算。
// // 所有其他列被保留在结果数据中。
// // dim5 是计算得到的 cluster index 。
// // dim6 是计算得到的距离值。
// // dimensions:
// // 0 1 2 3 4 5 6 7
// [ 232, 4.21, 51, 0.323, 'xxx', 0, 14, 0.145 ],
// [ 321, 1.62, 18, 0.139, 'xzx', 2, 24, 0.321 ],
// [ 551, 11.21, 13, 0.641, 'yzy', 0, 14, 0.145 ],
// ...
// ]
}, {
fromDatasetIndex: 1,
fromTransformResult: 1
// 本 dataset 得到的结果数据是例如:
// centroids: [
// // cluster0 的中心点数据。
// [14, 0.145],
// // cluster1 的中心点数据。
// [24, 0.321],
// ...
// ]
}]
```
* 独立使用
* `outputType: 'single'`:
* `result` - `object`. 例如
```js
result = {
data: [
// dim2, dim3 被用于聚类计算。
// 所有其他列被保留在结果数据中。
// dim5 是计算得到的 cluster index 。
// dim6 是计算得到的 squared distance 。
// dimensions:
// 0 1 2 3 4 5 6
[ 232, 4.21, 51, 0.323, 'xxx', 0, 89 ],
[ 321, 1.62, 18, 0.139, 'xzx', 2, 23 ],
[ 551, 11.21, 13, 0.641, 'yzy', 0, ?? ],
...
],
centroids: [
// cluster0 的中心。
[14, 0.145],
// cluster1 的中心。
[24, 0.321],
...
]
}
```
* `outputType: 'multiple'`:
* `result` - `object`. Including the centroids, and pointsInCluster. For example:
```js
result = {
pointsInCluster: [
// cluster0 中的数据项
[
[ 232, 4.21, 51, 0.323, 'xxx' ],
[ 551, 11.21, 13, 0.641, 'yzy' ],
...
],
// cluster1 中的数据项
[
[ 321, 1.62, 18, 0.139, 'xzx' ],
...
],
...
],
centroids: [
// cluster0 的中心。
[14, 0.145],
// cluster1 的中心。
[24, 0.321],
...
]
};
```

@@ -187,13 +326,6 @@ #### 实例

```html
<script src='https://cdn.bootcss.com/echarts/3.4.0/echarts.js'></script>
<script src='./dist/ecStat.js'></script>
<script>
[test/transform/clustering_bikmeans.html](https://github.com/ecomfe/echarts-stat/blob/master/test/transform/clustering_bikmeans.html)
[test/standalone/clustering_bikmeans.html](https://github.com/ecomfe/echarts-stat/blob/master/test/standalone/clustering_bikmeans.html)
var clusterNumber = 3;
var result = ecStat.clustering.hierarchicalKMeans(data, clusterNumber, false);
</script>
```
![static clustering](img/static-clustering.png)

@@ -205,13 +337,4 @@

```html
<script src='https://cdn.bootcss.com/echarts/3.4.0/echarts.js'></script>
<script src='./dist/ecStat.js'></script>
<script>
[test/standalone/clustering_animation.html](https://github.com/ecomfe/echarts-stat/blob/master/test/standalone/clustering_animation.html)
var clusterNumber = 6;
var result = ecStat.clustering.hierarchicalKMeans(data, clusterNumber, true);
</script>
```
![dynamic clustering](http://g.recordit.co/DTTS8d0D4O.gif)

@@ -227,38 +350,84 @@

#### 调用方式
```
var myRegression = ecStat.regression(regressionType, data, order);
```
* 作为 echarts transform 使用(echarts 5.0 开始支持)
```js
echarts.registerTransform(ecStat.transform.regression);
```
```js
chart.setOption({
dataset: [{
source: data
}, {
type: 'ecStat:regression',
config: {
method: regressionType,
...opt
}
}],
...
});
```
* 独立使用
```js
var myRegression = ecStat.regression(regressionType, data, opt);
// or
var myRegression = ecStat.regression('polynomial', data, order);
```
##### 参数说明
* `regressionType` - `string`. 回归类型,提供了四种类型的回归算法,分别是 `'linear'`, `'exponential'`, `'logarithmic'`, `'polynomial'`。
* `data` - `Array.<Array.<number>>`. 原始的输入数据是一个二维的数值数组,其中每个数据对象是包含两个数值属性的一维数组,分别表示自变量和因变量的值。如下:
```js
var data = [
* `regressionType` - `string`. 必填参数。回归类型,提供了四种类型的回归算法,分别是 `'linear'`, `'exponential'`, `'logarithmic'`, `'polynomial'`。
* `data` - `number[][]`. 原始的输入数据是一个二维的数值数组,其中每个数据对象是包含两个数值属性的一维数组,分别表示自变量和因变量的值。如下:
```js
var data = [
[1, 2],
[3, 5],
...
];
```
* `opt` - `object`.
* `opt.dimensions` - `(number | string)[]`. 可选参数。指定数据的哪些维度会被用于回归计算。默认为 `[0, 1]`。在“echarts transform”模式下,维度名(`string`)和维度序数(`number`)都可被指定。在“独立使用”模式下,只有维度序数可被指定(因为此模式下并没有支持定义维度名)。
* `order` - `number`. 可选参数。默认为 `2`。多项式的阶数(只在 `'polynomial'` 中生效)。对于非多项式回归,可以忽略该参数。
[1, 2],
[3, 5],
...
];
```
* `order` - `number`. 多项式的阶数。对于非多项式回归,可以忽略该参数。
##### 返回值说明
* `myRegression` - `Object`. 包括用于绘制折线图的拟合数据点 `points`,回归曲线的参数 `parameter`,以及拟合出的曲线表达式 `expression`。如下:
* 作为 echarts transform 使用(echarts 5.0 开始支持)
```js
dataset: [{
source: [...]
}, {
transform: 'ecStat:regression',
// // 本 dataset 得到的结果数据例如:
// [
// // ValueOnX, ValueOnY
// [ 23, 51 ],
// [ 24, 62 ],
// ...
// ]
// // config.dimensions 之外的其他维度的数据
// // 也会保留在结果中。
}]
```
* 独立使用
* `myRegression` - `object`. 包括用于绘制折线图的拟合数据点 `points`,回归曲线的参数 `parameter`,以及拟合出的曲线表达式 `expression`。如下:
```js
myRegression.points = [
[1, 2],
[3, 4],
...
];
```js
myRegression.points = [
// ValueOnX, ValueOnY
[ 23, 51 ],
[ 24, 62 ],
...
];
// config.dimensions 之外的其他维度的数据
// 也会保留在结果中。
// this is the parameter of linear regression, for other types, it shoule be a little different
myRegression.parameter = {
gradient: 1.695,
intercept: 3.008
};
// this is the parameter of linear regression,
// for other types, it shoule be a little different
myRegression.parameter = {
gradient: 1.695,
intercept: 3.008
};
myRegression.expression = 'y = 1.7x + 3.01';
```
myRegression.expression = 'y = 1.7x + 3.01';
```

@@ -271,12 +440,5 @@ #### 实例

```html
<script src='https://cdn.bootcss.com/echarts/3.4.0/echarts.js'></script>
<script src='./dist/ecStat.js'></script>
<script>
[test/transform/regression_linear.html](https://github.com/ecomfe/echarts-stat/blob/master/test/transform/regression_linear.html)
[test/standalone/regression_linear.html](https://github.com/ecomfe/echarts-stat/blob/master/test/standalone/regression_linear.html)
var myRegression = ecStat.regression('linear', data);
</script>
```
![linear regression](img/linear.png)

@@ -288,12 +450,5 @@

```html
<script src='https://cdn.bootcss.com/echarts/3.4.0/echarts.js'></script>
<script src='./dist/ecStat.js'></script>
<script>
[test/transform/regression_exponential.html](https://github.com/ecomfe/echarts-stat/blob/master/test/transform/regression_exponential.html)
[test/standalone/regression_exponential.html](https://github.com/ecomfe/echarts-stat/blob/master/test/standalone/regression_exponential.html)
var myRegression = ecStat.regression('exponential', data);
</script>
```
![exponential regression](img/exponential.png)

@@ -305,12 +460,5 @@

```html
<script src='https://cdn.bootcss.com/echarts/3.4.0/echarts.js'></script>
<script src='./dist/ecStat.js'></script>
<script>
[test/transform/regression_logarithmic.html](https://github.com/ecomfe/echarts-stat/blob/master/test/transform/regression_logarithmic.html)
[test/standalone/regression_logarithmic.html](https://github.com/ecomfe/echarts-stat/blob/master/test/standalone/regression_logarithmic.html)
var myRegression = ecStat.regression('logarithmic', data);
</script>
```
![logarithmic regression](img/logarithmic.png)

@@ -322,12 +470,5 @@

```html
<script src='https://cdn.bootcss.com/echarts/3.4.0/echarts.js'></script>
<script src='./dist/ecStat.js'></script>
<script>
[test/transform/regression_polynomial.html](https://github.com/ecomfe/echarts-stat/blob/master/test/transform/regression_polynomial.html)
[test/standalone/regression_polynomial.html](https://github.com/ecomfe/echarts-stat/blob/master/test/standalone/regression_polynomial.html)
var myRegression = ecStat.regression('polynomial', data, 3);
</script>
```
![polynomial regression](img/polynomial.png)

@@ -346,3 +487,3 @@

##### 调用方式
```
```js
var sampleDeviation = ecStat.statistics.deviation(dataList);

@@ -352,7 +493,7 @@ ```

* `dataList` : `Array.<number>`
* `dataList` : `number[]`. 输入的数值样本集。
##### 返回值说明
* `sampleDeviation`: `number`. Return the deviation of the numeric array *dataList*. If the *dataList* is empty or the length less than 2, return 0.
* `sampleDeviation`: `number`. 返回输入数组 *dataList* 的标准差。如果 *dataList* 为空或者长度小于 2,返回 0.

@@ -363,3 +504,3 @@

##### 调用方式
```
```js
var varianceValue = ecStat.statistics.sampleVariance(dataList);

@@ -369,7 +510,7 @@ ```

* `dataList` : `Array.<number>`
* `dataList` : `number[]`. 输入的数值样本集。
##### 返回值说明
* `varianceValue`: `number`. Return the variance of the numeric array *dataList*. If the *dataList* is empty or the length less than 2, return 0.
* `varianceValue`: `number`. 返回输入数组 *dataList* 的样本方差。如果 *dataList* 为空或者长度小于 2,返回 0.

@@ -380,3 +521,3 @@

##### 调用方式
```
```js
var quantileValue = ecStat.statistics.quantile(dataList, p);

@@ -386,8 +527,8 @@ ```

* `dataList` : `Array.<number>`. Sorted array of numbers.
* `p`: `number`. where 0 =< *p* <= 1. For example, the first quartile at p = 0.25, the seconed quartile at p = 0.5(same as the median), and the third quartile at p = 0.75.
* `dataList` : `number[]`. 输入的数值数组,该数组必须是按从小到大有序排列的.
* `p`: `number`. 分位数,取值在 [0, 1] 之间. 例如, 第一四分位数对应的 p 值是 0.25;第二四分位数,也就是中位数,对应的 p 值是 0.5;第三四分位数对应的 p 值是 0.75.
##### 返回值说明
* `quantileValue`: `number`. Return the *p*-quantile of the sorted array of numbers. If p <= 0 or the length of *dataList* less than 2, return the first element of the sorted array; if p >= 1, return the last element of the sorted array; If *dataList* is empty, return 0.
* `quantileValue`: `number`. 计算得到的分位数值。如果输入的 *p* 值小于等于 0 或者 *dataList* 的长度小于2,则返回有序数组 *dataList* 的第一个值;如果输入的 *p* 值大于等于1,则返回有序数组 *dataList* 的最后一个值;如果输入的有序数组 *dataList* 为空,则返回 0.

@@ -398,3 +539,3 @@

##### 调用方式
```
```js
var maxValue = ecStat.statistics.max(dataList);

@@ -404,7 +545,7 @@ ```

* `dataList` : `Array.<number>`
* `dataList` : `number[]`. 输入的数值样本集。
##### 返回值说明
* `maxValue`: `number`. The maximum value of the *dataList*.
* `maxValue`: `number`. 返回输入数组 *dataList* 的最大值。

@@ -415,3 +556,3 @@

##### 调用方式
```
```js
var minValue = ecStat.statistics.min(dataList);

@@ -421,7 +562,7 @@ ```

* `dataList` : `Array.<number>`
* `dataList` : `number[]`. 输入的数值样本集。
##### 返回值说明
* `minValue`: `number`. The minimum value of the *dataList*.
* `minValue`: `number`. 返回输入数组 *dataList* 的最小值。

@@ -432,3 +573,3 @@

##### 调用方式
```
```js
var meanValue = ecStat.statistics.mean(dataList);

@@ -438,7 +579,7 @@ ```

* `dataList` : `Array.<number>`
* `dataList` : `number[]`. 输入的数值样本集。
##### 返回值说明
* `meanValue`: `number`. The average of the *dataList*.
* `meanValue`: `number`. 返回输入数组 *dataList* 的平均值。

@@ -449,3 +590,3 @@

##### 调用方式
```
```js
var medianValue = ecStat.statistics.median(dataList);

@@ -455,7 +596,7 @@ ```

* `dataList` : `Array.<number>`. Sorted array of numbers
* `dataList` : `number[]`. 输入的数值数组,该数组必须是按从小到大有序排列的.
##### 返回值说明
* `medianValue`: `number`. The median of the *dataList*.
* `medianValue`: `number`. 返回输入数组 *dataList* 的中位数。

@@ -466,3 +607,3 @@

##### 调用方式
```
```js
var sumValue = ecStat.statistics.sum(dataList);

@@ -472,9 +613,9 @@ ```

* `dataList` : `Array.<number>`
* `dataList` : `number[]`. 输入的数值样本集。
##### 返回值说明
* `sumValue`: `number`. The sum of the *dataList*.
* `sumValue`: `number`. 返回输入数组 *dataList* 的求和结果。

@@ -5,23 +5,63 @@ define(function (require) {

var dataPreprocess = dataProcess.dataPreprocess;
var array = require('./util/array');
var arraySize = array.size;
var sumOfColumn = array.sumOfColumn;
var arraySum = array.sum;
var zeros = array.zeros;
var isArray = array.isArray;
var mathSqrt = Math.sqrt;
var normalizeDimensions = dataProcess.normalizeDimensions;
var arrayUtil = require('./util/array');
var numberUtil = require('./util/number');
var arraySize = arrayUtil.size;
var sumOfColumn = arrayUtil.sumOfColumn;
var arraySum = arrayUtil.sum;
var zeros = arrayUtil.zeros;
// var isArray = arrayUtil.isArray;
var numberUtil = require('./util/number');
var isNumber = numberUtil.isNumber;
var mathPow = Math.pow;
var OutputType = {
/**
* Data are all in one. Cluster info are added as an attribute of data.
* ```ts
* type OutputDataSingle = {
* // Each index of `data` is the index of the input data.
* data: OutputDataItem[];
* // The index of `centroids` is the cluster index.
* centroids: [ValueOnX, ValueOnY][];
* };
* type InputDataItem = (ValueOnX | ValueOnY | OtherValue)[];
* type OutputDataItem = (...InputDataItem | ClusterIndex | SquareDistanceToCentroid)[];
* ```
*/
SINGLE: 'single',
/**
* Data are separated by cluster. Suitable for retrieving data form each cluster.
* ```ts
* type OutputDataMultiple = {
* // Each index of `clusterAssment` is the index of the input data.
* clusterAssment: [ClusterIndex, SquareDistanceToCentroid][];
* // The index of `centroids` is the cluster index.
* centroids: [ValueOnX, ValueOnY][];
* // The index of `pointsInCluster` is the cluster index.
* pointsInCluster: DataItemListInOneCluster[];
* }
* type DataItemListInOneCluster = InputDataItem[];
* type InputDataItem = (ValueOnX | ValueOnY | OtherValue)[];
* type SquareDistanceToCentroid = number;
* type ClusterIndex = number;
* type ValueOnX = number;
* type ValueOnY = number;
* type OtherValue = unknown;
* ```
*/
MULTIPLE: 'multiple'
}
/**
* KMeans of clustering algorithm
* @param {Array.<Array.<number>>} data two-dimension array
* @param {number} k the number of clusters in a dataset
* KMeans of clustering algorithm.
* @param {Array.<Array.<number>>} data two-dimension array
* @param {number} k the number of clusters in a dataset
* @return {Object}
*/
function kMeans(data, k) {
function kMeans(data, k, dataMeta) {
var size = arraySize(data);
// create array to assign data points to centroids, also holds SE of each point
var clusterAssigned = zeros(size[0], 2);
var centroids = createRandCent(data, k);
var clusterAssigned = zeros(data.length, 2);
var centroids = createRandCent(k, calcExtents(data, dataMeta.dimensions));
var clusterChanged = true;

@@ -35,7 +75,7 @@ var minDist;

clusterChanged = false;
for (var i = 0; i < size[0]; i++) {
for (var i = 0; i < data.length; i++) {
minDist = Infinity;
minIndex = -1;
for (var j = 0; j < k; j++) {
distIJ = distEuclid(data[i], centroids[j]);
distIJ = distEuclid(data[i], centroids[j], dataMeta);
if (distIJ < minDist) {

@@ -50,3 +90,3 @@ minDist = distIJ;

clusterAssigned[i][0] = minIndex;
clusterAssigned[i][1] = mathPow(minDist, 2);
clusterAssigned[i][1] = minDist;
}

@@ -61,3 +101,3 @@ //recalculate centroids

}
centroids[i] = meanInColumns(ptsInClust);
centroids[i] = meanInColumns(ptsInClust, dataMeta);
}

@@ -75,18 +115,15 @@ }

* Calculate the average of each column in a two-dimensional array
* and returns the values as an array.
* @param {Array.<Array>} dataList two-dimensional array
* @return {Array}
* and returns the values as an array.
*/
function meanInColumns(dataList) {
var size = arraySize(dataList);
function meanInColumns(dataList, dataMeta) {
var meanArray = [];
var sum;
var mean;
for (var j = 0; j < size[1]; j++) {
for (var j = 0; j < dataMeta.dimensions.length; j++) {
var dimIdx = dataMeta.dimensions[j];
sum = 0;
for (var i = 0; i < size[0]; i++) {
sum += dataList[i][j];
for (var i = 0; i < dataList.length; i++) {
sum += dataList[i][dimIdx];
}
mean = sum / size[0];
mean = sum / dataList.length;
meanArray.push(mean);

@@ -99,22 +136,84 @@ }

* The combine of hierarchical clustering and k-means.
* @param {Array} data two-dimension array.
* @param {[type]} k the number of clusters in a dataset. It has to be greater than 1.
* @param {boolean} stepByStep
* @return {}
* @param {Array} data two-dimension array.
* @param {Object|number} [clusterCountOrConfig] config or clusterCountOrConfig.
* @param {number} clusterCountOrConfig.clusterCount Mandatory.
* The number of clusters in a dataset. It has to be greater than 1.
* @param {boolean} [clusterCountOrConfig.stepByStep=false] Optional.
* @param {OutputType} [clusterCountOrConfig.outputType='multiple'] Optional.
* See `OutputType`.
* @param {number} [clusterCountOrConfig.outputClusterIndexDimension] Mandatory.
* Only work in `OutputType.SINGLE`.
* @param {number} [clusterCountOrConfig.outputCentroidDimensions] Optional.
* If specified, the centroid will be set to those dimensions of the result data one by one.
* By default not set centroid to result.
* Only work in `OutputType.SINGLE`.
* @param {Array.<number>} [clusterCountOrConfig.dimensions] Optional.
* Target dimensions to calculate the regression.
* By default: use all of the data.
* @return {Array} See `OutputType`.
*/
function hierarchicalKMeans(data, k, stepByStep) {
if (k < 2 ) {
function hierarchicalKMeans(data, clusterCountOrConfig, stepByStep) {
var config = (
isNumber(clusterCountOrConfig)
? {clusterCount: clusterCountOrConfig, stepByStep: stepByStep}
: clusterCountOrConfig
) || {clusterCount: 2};
var k = config.clusterCount;
if (k < 2) {
return;
}
var dataSet = dataPreprocess(data);
var size = arraySize(dataSet);
var clusterAssment = zeros(size[0], 2);
// initial center point
var centroid0 = meanInColumns(dataSet);
var dataMeta = parseDataMeta(data, config);
var isOutputTypeSingle = dataMeta.outputType === OutputType.SINGLE;
var dataSet = dataPreprocess(data, {dimensions: dataMeta.dimensions});
var clusterAssment = zeros(dataSet.length, 2);
var outputSingleData;
var setClusterIndex;
var getClusterIndex;
function setDistance(dataIndex, dist) {
clusterAssment[dataIndex][1] = dist;
}
function getDistance(dataIndex) {
return clusterAssment[dataIndex][1];
};
if (isOutputTypeSingle) {
outputSingleData = [];
var outputClusterIndexDimension = dataMeta.outputClusterIndexDimension;
setClusterIndex = function (dataIndex, clusterIndex) {
outputSingleData[dataIndex][outputClusterIndexDimension] = clusterIndex;
};
getClusterIndex = function (dataIndex) {
return outputSingleData[dataIndex][outputClusterIndexDimension];
};
for (var i = 0; i < dataSet.length; i++) {
outputSingleData.push(dataSet[i].slice());
setDistance(i, 0);
setClusterIndex(i, 0);
}
}
else {
setClusterIndex = function (dataIndex, clusterIndex) {
clusterAssment[dataIndex][0] = clusterIndex;
};
getClusterIndex = function (dataIndex) {
return clusterAssment[dataIndex][0];
};
}
// initial center point.
var centroid0 = meanInColumns(dataSet, dataMeta);
var centList = [centroid0];
var squareError;
for (var i = 0; i < size[0]; i++) {
squareError = distEuclid(dataSet[i], centroid0);
clusterAssment[i][1] = mathPow(squareError, 2);
for (var i = 0; i < dataSet.length; i++) {
var dist = distEuclid(dataSet[i], centroid0, dataMeta);
setDistance(i, dist);
}
var lowestSSE;

@@ -128,4 +227,10 @@ var ptsInClust;

var result = {
data: outputSingleData,
centroids: centList,
isEnd: false
};
if (!isOutputTypeSingle) {
// Only for backward compat.
result.clusterAssment = clusterAssment;
}

@@ -144,11 +249,11 @@ function oneStep() {

ptsNotClust = [];
for (var i = 0; i < clusterAssment.length; i++) {
if (clusterAssment[i][0] === j) {
for (var i = 0; i < dataSet.length; i++) {
if (getClusterIndex(i) === j) {
ptsInClust.push(dataSet[i]);
}
else {
ptsNotClust.push(clusterAssment[i][1]);
ptsNotClust.push(getDistance(i));
}
}
clusterInfo = kMeans(ptsInClust, 2);
clusterInfo = kMeans(ptsInClust, 2, dataMeta);
sseSplit = sumOfColumn(clusterInfo.clusterAssigned, 1);

@@ -175,6 +280,6 @@ sseNotSplit = arraySum(ptsNotClust);

centList.push(newCentroid[1]);
for ( i = 0, j = 0; i < clusterAssment.length && j < newClusterAss.length; i++) {
if (clusterAssment[i][0] === centSplit) {
clusterAssment[i][0] = newClusterAss[j][0];
clusterAssment[i][1] = newClusterAss[j++][1];
for (var i = 0, j = 0; i < dataSet.length && j < newClusterAss.length; i++) {
if (getClusterIndex(i) === centSplit) {
setClusterIndex(i, newClusterAss[j][0]);
setDistance(i, newClusterAss[j++][1]);
}

@@ -184,16 +289,14 @@ }

var pointInClust = [];
for (var i = 0; i < centList.length; i++) {
pointInClust[i] = [];
for (var j = 0; j < clusterAssment.length; j++) {
if (clusterAssment[j][0] === i) {
pointInClust[i].push(dataSet[j]);
if (!isOutputTypeSingle) {
for (var i = 0; i < centList.length; i++) {
pointInClust[i] = [];
for (var j = 0; j < dataSet.length; j++) {
if (getClusterIndex(j) === i) {
pointInClust[i].push(dataSet[j]);
}
}
}
result.pointsInCluster = pointInClust;
}
result.clusterAssment = clusterAssment;
result.centroids = centList;
result.pointsInCluster = pointInClust;
index++;

@@ -204,19 +307,35 @@ }

}
return result;
}
var step = {
next: oneStep
};
if (!stepByStep) {
var result;
while (!(result = step.next()).isEnd);
return result;
if (!config.stepByStep) {
while (oneStep(), !result.isEnd);
}
else {
return step;
result.next = function () {
oneStep();
setCentroidToResultData(result, dataMeta);
return result;
};
}
setCentroidToResultData(result, dataMeta);
return result;
}
function setCentroidToResultData(result, dataMeta) {
var outputCentroidDimensions = dataMeta.outputCentroidDimensions;
if (dataMeta.outputType !== OutputType.SINGLE || outputCentroidDimensions == null) {
return;
}
var outputSingleData = result.data;
var centroids = result.centroids;
for (var i = 0; i < outputSingleData.length; i++) {
var line = outputSingleData[i];
var clusterIndex = line[dataMeta.outputClusterIndexDimension];
var centroid = centroids[clusterIndex];
var dimLen = Math.min(centroid.length, outputCentroidDimensions.length);
for (var j = 0; j < dimLen; j++) {
line[outputCentroidDimensions[j]] = centroid[j];
}
}
}

@@ -226,28 +345,11 @@

* Create random centroid of kmeans.
* @param {Array.<number>} dataSet two-dimension array
* @param {number} k the number of centroids to be created
* @return {Array.<number>} random centroids of kmeans
*/
function createRandCent(dataSet, k) {
var size = arraySize(dataSet);
function createRandCent(k, extents) {
//constructs a two-dimensional array with all values 0
var centroids = zeros(k, size[1]);
var minJ;
var maxJ;
var rangeJ;
var centroids = zeros(k, extents.length);
//create random cluster centers, within bounds of each dimension
for (var j = 0; j < size[1]; j++) {
minJ = dataSet[0][j];
maxJ = dataSet[0][j];
for (var i = 1; i < size[0]; i++) {
if (dataSet[i][j] < minJ) {
minJ = dataSet[i][j];
}
if (dataSet[i][j] > maxJ) {
maxJ = dataSet[i][j];
}
}
rangeJ = maxJ - minJ;
for (var j = 0; j < extents.length; j++) {
var extentItem = extents[j];
for (var i = 0; i < k; i++) {
centroids[i][j] = minJ + rangeJ * Math.random();
centroids[i][j] = extentItem.min + extentItem.span * Math.random();
}

@@ -260,23 +362,76 @@ }

* Distance method for calculating similarity
* @param {Array.<number>} vec1
* @param {Array.<nnumber>} vec2
* @return {number}
*/
function distEuclid(vec1, vec2) {
function distEuclid(dataItem, centroid, dataMeta) {
// The distance should be normalized between different dimensions,
// otherwise they may provide different weight in the final distance.
// The greater weight offers more effect in the cluster determination.
if (!isArray(vec1) && !isArray(vec2)) {
return mathSqrt(mathPow(vec1 - vec2, 2));
}
var powerSum = 0;
var dimensions = dataMeta.dimensions;
var extents = dataMeta.rawExtents;
//subtract the corresponding elements in the vectors
for (var i = 0; i < vec1.length; i++) {
powerSum += mathPow(vec1[i] - vec2[i], 2);
for (var i = 0; i < dimensions.length; i++) {
var span = extents[i].span;
// If span is 0, do not count.
if (span) {
var dimIdx = dimensions[i];
var dist = (dataItem[dimIdx] - centroid[i]) / span;
powerSum += mathPow(dist, 2);
}
}
return mathSqrt(powerSum);
return powerSum;
}
function parseDataMeta(dataSet, config) {
var size = arraySize(dataSet);
if (size.length < 1) {
throw new Error('The input data of clustering should be two-dimension array.');
}
var colCount = size[1];
var defaultDimensions = [];
for (var i = 0; i < colCount; i++) {
defaultDimensions.push(i);
}
var dimensions = normalizeDimensions(config.dimensions, defaultDimensions);
var outputType = config.outputType || OutputType.MULTIPLE;
var outputClusterIndexDimension = config.outputClusterIndexDimension;
if (outputType === OutputType.SINGLE && !numberUtil.isNumber(outputClusterIndexDimension)) {
throw new Error('outputClusterIndexDimension is required as a number.');
}
var extents = calcExtents(dataSet, dimensions);
return {
dimensions: dimensions,
rawExtents: extents,
outputType: outputType,
outputClusterIndexDimension: outputClusterIndexDimension,
outputCentroidDimensions: config.outputCentroidDimensions,
};
}
function calcExtents(dataSet, dimensions) {
var extents = [];
var dimLen = dimensions.length;
for (var i = 0; i < dimLen; i++) {
extents.push({ min: Infinity, max: -Infinity });
}
for (var i = 0; i < dataSet.length; i++) {
var line = dataSet[i];
for (var j = 0; j < dimLen; j++) {
var extentItem = extents[j];
var val = line[dimensions[j]];
extentItem.min > val && (extentItem.min = val);
extentItem.max < val && (extentItem.max = val);
}
}
for (var i = 0; i < dimLen; i++) {
extents[i].span = extents[i].max - extents[i].min;
}
return extents;
}
return {
kMeans: kMeans,
OutputType: OutputType,
hierarchicalKMeans: hierarchicalKMeans

@@ -283,0 +438,0 @@ };

@@ -11,6 +11,7 @@ //

data: OutputData
customData:OutputData
}
interface HistogramBinsBin {
x0: number
y0: number
x1: number
sample: Array<number>

@@ -17,0 +18,0 @@ }

@@ -8,6 +8,12 @@ define(function (require) {

statistics: require('./statistics'),
histogram: require('./histogram')
histogram: require('./histogram'),
transform: {
regression: require('./transform/regression'),
histogram: require('./transform/histogram'),
clustering: require('./transform/clustering')
}
};
});

@@ -9,3 +9,3 @@ define(function (require) {

var dataPreprocess = dataProcess.dataPreprocess;
var getPrecision = dataProcess.getPrecision;
var normalizeDimensions = dataProcess.normalizeDimensions;
var array = require('./util/array');

@@ -21,28 +21,37 @@ var ascending = array.ascending;

* @param {Array.<number>} data
* @param {string} threshold
* @param {Object|string} optOrMethod Optional settings or `method`.
* @param {Object|string} optOrMethod.method 'squareRoot' | 'scott' | 'freedmanDiaconis' | 'sturges'
* @param {Array.<number>|number} optOrMethod.dimensions If data is a 2-d array,
* which dimension will be used to calculate histogram.
* @return {Object}
*/
function computeBins(data, threshold) {
function computeBins(data, optOrMethod) {
var opt = typeof optOrMethod === 'string'
? { method: optOrMethod }
: (optOrMethod || {});
if (threshold == null) {
threshold = thresholdMethod.squareRoot;
}
else {
threshold = thresholdMethod[threshold];
}
var values = dataPreprocess(data);
var threshold = opt.method == null
? thresholdMethod.squareRoot
: thresholdMethod[opt.method];
var dimensions = normalizeDimensions(opt.dimensions);
var values = dataPreprocess(data, {
dimensions: dimensions,
toOneDimensionArray: true
});
var maxValue = max(values);
var minValue = min(values);
var binsNumber = threshold(values, minValue, maxValue);
var step = tickStep(minValue, maxValue, binsNumber);
var precision = -Math.floor(Math.log(Math.abs(maxValue - minValue) / binsNumber) / Math.LN10);
var tickStepResult = tickStep(minValue, maxValue, binsNumber);
var step = tickStepResult.step;
var toFixedPrecision = tickStepResult.toFixedPrecision;
// return the xAxis coordinate for each bins, except the end point of the value
var rangeArray = range(
// use function toFixed() to avoid data like '0.700000001'
+((Math.ceil(minValue / step) * step).toFixed(precision)),
+((Math.floor(maxValue / step) * step).toFixed(precision)),
step,
precision
);
// use function toFixed() to avoid data like '0.700000001'
+((Math.ceil(minValue / step) * step).toFixed(toFixedPrecision)),
+((Math.floor(maxValue / step) * step).toFixed(toFixedPrecision)),
step,
toFixedPrecision
);

@@ -56,3 +65,3 @@ var len = rangeArray.length;

bins[i].sample = [];
bins[i].x0 = i > 0
bins[i].x0 = i > 0
? rangeArray[i - 1]

@@ -77,3 +86,9 @@ : (rangeArray[i] - minValue) === step

// use function toFixed() to avoid data like '6.5666638489'
return [+((bin.x0 + bin.x1) / 2).toFixed(precision), bin.sample.length];
return [
+((bin.x0 + bin.x1) / 2).toFixed(toFixedPrecision),
bin.sample.length,
bin.x0,
bin.x1,
bin.x0 + ' - ' + bin.x1
];
});

@@ -80,0 +95,0 @@

@@ -5,2 +5,3 @@ define(function (require) {

var dataPreprocess = dataProcess.dataPreprocess;
var normalizeDimensions = dataProcess.normalizeDimensions;

@@ -11,8 +12,7 @@ var regreMethods = {

* Common linear regression algorithm
* @param {Array.<Array.<number>>} data two-dimensional array
* @return {Object}
*/
linear: function (data) {
linear: function (predata, opt) {
var predata = dataPreprocess(data);
var xDimIdx = opt.dimensions[0];
var yDimIdx = opt.dimensions[1];
var sumX = 0;

@@ -25,6 +25,7 @@ var sumY = 0;

for (var i = 0; i < len; i++) {
sumX += predata[i][0];
sumY += predata[i][1];
sumXY += predata[i][0] * predata[i][1];
sumXX += predata[i][0] * predata[i][0];
var rawItem = predata[i];
sumX += rawItem[xDimIdx];
sumY += rawItem[yDimIdx];
sumXY += rawItem[xDimIdx] * rawItem[yDimIdx];
sumXX += rawItem[xDimIdx] * rawItem[xDimIdx];
}

@@ -37,7 +38,10 @@

for (var j = 0; j < predata.length; j++) {
var coordinate = [predata[j][0], gradient * predata[j][0] + intercept];
result.push(coordinate);
var rawItem = predata[j];
var resultItem = rawItem.slice();
resultItem[xDimIdx] = rawItem[xDimIdx];
resultItem[yDimIdx] = gradient * rawItem[xDimIdx] + intercept;
result.push(resultItem);
}
var string = 'y = ' + Math.round(gradient * 100) / 100 + 'x + ' + Math.round(intercept * 100) / 100;
var expression = 'y = ' + Math.round(gradient * 100) / 100 + 'x + ' + Math.round(intercept * 100) / 100;

@@ -50,3 +54,3 @@ return {

},
expression: string
expression: expression
};

@@ -58,8 +62,7 @@ },

* instead of linear.
* @param {Array.<Array>} data two-dimensional number array
* @return {Object}
*/
linearThroughOrigin: function (data) {
linearThroughOrigin: function (predata, opt) {
var predata = dataPreprocess(data);
var xDimIdx = opt.dimensions[0];
var yDimIdx = opt.dimensions[1];
var sumXX = 0;

@@ -69,4 +72,5 @@ var sumXY = 0;

for (var i = 0; i < predata.length; i++) {
sumXX += predata[i][0] * predata[i][0];
sumXY += predata[i][0] * predata[i][1];
var rawItem = predata[i];
sumXX += rawItem[xDimIdx] * rawItem[xDimIdx];
sumXY += rawItem[xDimIdx] * rawItem[yDimIdx];
}

@@ -78,7 +82,10 @@

for (var j = 0; j < predata.length; j++) {
var coordinate = [predata[j][0], predata[j][0] * gradient];
result.push(coordinate);
var rawItem = predata[j];
var resultItem = rawItem.slice();
resultItem[xDimIdx] = rawItem[xDimIdx];
resultItem[yDimIdx] = rawItem[xDimIdx] * gradient;
result.push(resultItem);
}
var string = 'y = ' + Math.round(gradient * 100) / 100 + 'x';
var expression = 'y = ' + Math.round(gradient * 100) / 100 + 'x';

@@ -90,3 +97,3 @@ return {

},
expression: string
expression: expression
};

@@ -97,8 +104,7 @@ },

* Exponential regression
* @param {Array.<Array.<number>>} data two-dimensional number array
* @return {Object}
*/
exponential: function (data) {
exponential: function (predata, opt) {
var predata = dataPreprocess(data);
var xDimIdx = opt.dimensions[0];
var yDimIdx = opt.dimensions[1];
var sumX = 0;

@@ -112,8 +118,9 @@ var sumY = 0;

for (var i = 0; i < predata.length; i++) {
sumX += predata[i][0];
sumY += predata[i][1];
sumXY += predata[i][0] * predata[i][1];
sumXXY += predata[i][0] * predata[i][0] * predata[i][1];
sumYlny += predata[i][1] * Math.log(predata[i][1]);
sumXYlny += predata[i][0] * predata[i][1] * Math.log(predata[i][1]);
var rawItem = predata[i];
sumX += rawItem[xDimIdx];
sumY += rawItem[yDimIdx];
sumXY += rawItem[xDimIdx] * rawItem[yDimIdx];
sumXXY += rawItem[xDimIdx] * rawItem[xDimIdx] * rawItem[yDimIdx];
sumYlny += rawItem[yDimIdx] * Math.log(rawItem[yDimIdx]);
sumXYlny += rawItem[xDimIdx] * rawItem[yDimIdx] * Math.log(rawItem[yDimIdx]);
}

@@ -127,7 +134,10 @@

for (var j = 0; j < predata.length; j++) {
var coordinate = [predata[j][0], coefficient * Math.pow(Math.E, index * predata[j][0])];
result.push(coordinate);
var rawItem = predata[j];
var resultItem = rawItem.slice();
resultItem[xDimIdx] = rawItem[xDimIdx];
resultItem[yDimIdx] = coefficient * Math.pow(Math.E, index * rawItem[xDimIdx]);
result.push(resultItem);
}
var string = 'y = ' + Math.round(coefficient * 100) / 100 + 'e^(' + Math.round(index * 100) / 100 + 'x)';
var expression = 'y = ' + Math.round(coefficient * 100) / 100 + 'e^(' + Math.round(index * 100) / 100 + 'x)';

@@ -140,3 +150,3 @@ return {

},
expression: string
expression: expression
};

@@ -148,8 +158,7 @@

* Logarithmic regression
* @param {Array.<Array.<number>>} data two-dimensional number array
* @return {Object}
*/
logarithmic: function (data) {
logarithmic: function (predata, opt) {
var predata = dataPreprocess(data);
var xDimIdx = opt.dimensions[0];
var yDimIdx = opt.dimensions[1];
var sumlnx = 0;

@@ -161,6 +170,7 @@ var sumYlnx = 0;

for (var i = 0; i < predata.length; i++) {
sumlnx += Math.log(predata[i][0]);
sumYlnx += predata[i][1] * Math.log(predata[i][0]);
sumY += predata[i][1];
sumlnxlnx += Math.pow(Math.log(predata[i][0]), 2);
var rawItem = predata[i];
sumlnx += Math.log(rawItem[xDimIdx]);
sumYlnx += rawItem[yDimIdx] * Math.log(rawItem[xDimIdx]);
sumY += rawItem[yDimIdx];
sumlnxlnx += Math.pow(Math.log(rawItem[xDimIdx]), 2);
}

@@ -173,7 +183,10 @@

for (var j = 0; j < predata.length; j++) {
var coordinate = [predata[j][0], gradient * Math.log(predata[j][0]) + intercept];
result.push(coordinate);
var rawItem = predata[j];
var resultItem = rawItem.slice();
resultItem[xDimIdx] = rawItem[xDimIdx];
resultItem[yDimIdx] = gradient * Math.log(rawItem[xDimIdx]) + intercept;
result.push(resultItem);
}
var string =
var expression =
'y = '

@@ -190,3 +203,3 @@ + Math.round(intercept * 100) / 100

},
expression: string
expression: expression
};

@@ -198,10 +211,10 @@

* Polynomial regression
* @param {Array.<Array.<number>>} data two-dimensional number array
* @param {number} order order of polynomials
* @return {Object}
*/
polynomial: function (data, order) {
polynomial: function (predata, opt) {
var predata = dataPreprocess(data);
if (typeof order === 'undefined') {
var xDimIdx = opt.dimensions[0];
var yDimIdx = opt.dimensions[1];
var order = opt.order;
if (order == null) {
order = 2;

@@ -217,3 +230,4 @@ }

for (var n = 0; n < predata.length; n++) {
sumA += predata[n][1] * Math.pow(predata[n][0], i);
var rawItem = predata[n];
sumA += rawItem[yDimIdx] * Math.pow(rawItem[xDimIdx], i);
}

@@ -226,3 +240,3 @@ lhs.push(sumA);

for (var m = 0; m < predata.length; m++) {
sumB += Math.pow(predata[m][0], i + j);
sumB += Math.pow(predata[m][xDimIdx], i + j);
}

@@ -241,18 +255,22 @@ temp.push(sumB);

var value = 0;
var rawItem = predata[i];
for (var n = 0; n < coeArray.length; n++) {
value += coeArray[n] * Math.pow(predata[i][0], n);
value += coeArray[n] * Math.pow(rawItem[xDimIdx], n);
}
result.push([predata[i][0], value]);
var resultItem = rawItem.slice();
resultItem[xDimIdx] = rawItem[xDimIdx];
resultItem[yDimIdx] = value;
result.push(resultItem);
}
var string = 'y = ';
var expression = 'y = ';
for (var i = coeArray.length - 1; i >= 0; i--) {
if (i > 1) {
string += Math.round(coeArray[i] * Math.pow(10, i + 1)) / Math.pow(10, i + 1) + 'x^' + i + ' + ';
expression += Math.round(coeArray[i] * Math.pow(10, i + 1)) / Math.pow(10, i + 1) + 'x^' + i + ' + ';
}
else if (i === 1) {
string += Math.round(coeArray[i] * 100) / 100 + 'x' + ' + ';
expression += Math.round(coeArray[i] * 100) / 100 + 'x' + ' + ';
}
else {
string += Math.round(coeArray[i] * 100) / 100;
expression += Math.round(coeArray[i] * 100) / 100;
}

@@ -264,3 +282,3 @@ }

parameter: coeArray,
expression: string
expression: expression
};

@@ -316,6 +334,31 @@

var regression = function (regreMethod, data, order) {
/**
* @param {string} regreMethod
* @param {Array.<Array.<number>>} data two-dimensional number array
* @param {Object|number} [optOrOrder] opt or order
* @param {number} [optOrOrder.order] order of polynomials
* @param {Array.<number>|number} [optOrOrder.dimensions=[0, 1]] Target dimensions to calculate the regression.
* By defualt: use [0, 1] as [x, y].
* @return {Array}
*/
var regression = function (regreMethod, data, optOrOrder) {
var opt = typeof optOrOrder === 'number'
? { order: optOrOrder }
: (optOrOrder || {});
return regreMethods[regreMethod](data, order);
var dimensions = normalizeDimensions(opt.dimensions, [0, 1]);
var predata = dataPreprocess(data, { dimensions: dimensions });
var result = regreMethods[regreMethod](predata, {
order: opt.order,
dimensions: dimensions
});
// Sort for line chart.
var xDimIdx = dimensions[0];
result.points.sort(function (itemA, itemB) {
return itemA[xDimIdx] - itemB[xDimIdx];
});
return result;
};

@@ -322,0 +365,0 @@

@@ -139,3 +139,2 @@ define(function (require) {

return {

@@ -142,0 +141,0 @@ size: size,

@@ -10,2 +10,16 @@ define(function (require) {

/**
* @param {Array.<number>|number} dimensions like `[2, 4]` or `4`
* @param {Array.<number>} [defaultDimensions=undefined] By default `undefined`.
* @return {Array.<number>} number like `4` is normalized to `[4]`,
* `null`/`undefined` is normalized to `defaultDimensions`.
*/
function normalizeDimensions(dimensions, defaultDimensions) {
return typeof dimensions === 'number'
? [dimensions]
: dimensions == null
? defaultDimensions
: dimensions;
}
/**
* Data preprocessing, filter the wrong data object.

@@ -17,6 +31,27 @@ * for example [12,] --- missing y value

* @param {Array.<Array>} data
* @param {Object?} [opt]
* @param {Array.<number>} [opt.dimensions] Optional. Like [2, 4],
* means that dimension index 2 and dimension index 4 need to be number.
* If null/undefined (by default), all dimensions need to be number.
* @param {boolean} [opt.toOneDimensionArray] Convert to one dimension array.
* Each value is from `opt.dimensions[0]` or dimension 0.
* @return {Array.<Array.<number>>}
*/
function dataPreprocess(data) {
function dataPreprocess(data, opt) {
opt = opt || {};
var dimensions = opt.dimensions;
var numberDimensionMap = {};
if (dimensions != null) {
for (var i = 0; i < dimensions.length; i++) {
numberDimensionMap[dimensions[i]] = true;
}
}
var targetOneDim = opt.toOneDimensionArray
? (dimensions ? dimensions[0] : 0)
: null;
function shouldBeNumberDimension(dimIdx) {
return !dimensions || numberDimensionMap.hasOwnProperty(dimIdx);
}
if (!isArray(data)) {

@@ -29,7 +64,6 @@ throw new Error('Invalid data type, you should input an array');

if (arraySize.length === 1) {
for (var i = 0; i < arraySize[0]; i++) {
if (isNumber(data[i])) {
predata.push(data[i]);
var item = data[i];
if (isNumber(item)) {
predata.push(item);
}

@@ -39,8 +73,7 @@ }

else if (arraySize.length === 2) {
for (var i = 0; i < arraySize[0]; i++) {
var isCorrect = true;
var item = data[i];
for (var j = 0; j < arraySize[1]; j++) {
if (!isNumber(data[i][j])) {
if (shouldBeNumberDimension(j) && !isNumber(item[j])) {
isCorrect = false;

@@ -50,3 +83,7 @@ }

if (isCorrect) {
predata.push(data[i]);
predata.push(
targetOneDim != null
? item[targetOneDim]
: item
);
}

@@ -70,2 +107,3 @@ }

return {
normalizeDimensions: normalizeDimensions,
dataPreprocess: dataPreprocess,

@@ -72,0 +110,0 @@ getPrecision: getPrecision

@@ -23,7 +23,20 @@ define(function (require) {

function quantityExponent(val) {
if (val === 0) {
return 0;
}
var exp = Math.floor(Math.log(val) / Math.LN10);
// Fix pricision loss.
if (val / Math.pow(10, exp) >= 10) {
exp++;
}
return exp;
}
return {
isNumber: isNumber,
isInteger: isInteger
isInteger: isInteger,
quantityExponent: quantityExponent
};
});
define(function (require) {
var numberUtil = require('./number');
/**

@@ -13,3 +15,4 @@ * Computing the length of step

var step0 = Math.abs(stop - start) / count;
var precision = Math.floor(Math.log(step0) / Math.LN10);
var precision = numberUtil.quantityExponent(step0);
var step1 = Math.pow(10, precision);

@@ -27,6 +30,14 @@ var error = step0 / step1;

}
return +((stop >= start ? step1 : -step1).toFixed(-precision));
var toFixedPrecision = precision < 0 ? -precision : 0;
var resultStep = +(
(stop >= start ? step1 : -step1).toFixed(toFixedPrecision)
);
return {
step: resultStep,
toFixedPrecision: toFixedPrecision
};
};
});

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc