time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

vector.js (14870B)


      1 (function(jStat, Math) {
      2 
      3 var isFunction = jStat.utils.isFunction;
      4 
      5 // Ascending functions for sort
      6 function ascNum(a, b) { return a - b; }
      7 
      8 function clip(arg, min, max) {
      9   return Math.max(min, Math.min(arg, max));
     10 }
     11 
     12 
     13 // sum of an array
     14 jStat.sum = function sum(arr) {
     15   var sum = 0;
     16   var i = arr.length;
     17   while (--i >= 0)
     18     sum += arr[i];
     19   return sum;
     20 };
     21 
     22 
     23 // sum squared
     24 jStat.sumsqrd = function sumsqrd(arr) {
     25   var sum = 0;
     26   var i = arr.length;
     27   while (--i >= 0)
     28     sum += arr[i] * arr[i];
     29   return sum;
     30 };
     31 
     32 
     33 // sum of squared errors of prediction (SSE)
     34 jStat.sumsqerr = function sumsqerr(arr) {
     35   var mean = jStat.mean(arr);
     36   var sum = 0;
     37   var i = arr.length;
     38   var tmp;
     39   while (--i >= 0) {
     40     tmp = arr[i] - mean;
     41     sum += tmp * tmp;
     42   }
     43   return sum;
     44 };
     45 
     46 // sum of an array in each row
     47 jStat.sumrow = function sumrow(arr) {
     48   var sum = 0;
     49   var i = arr.length;
     50   while (--i >= 0)
     51     sum += arr[i];
     52   return sum;
     53 };
     54 
     55 // product of an array
     56 jStat.product = function product(arr) {
     57   var prod = 1;
     58   var i = arr.length;
     59   while (--i >= 0)
     60     prod *= arr[i];
     61   return prod;
     62 };
     63 
     64 
     65 // minimum value of an array
     66 jStat.min = function min(arr) {
     67   var low = arr[0];
     68   var i = 0;
     69   while (++i < arr.length)
     70     if (arr[i] < low)
     71       low = arr[i];
     72   return low;
     73 };
     74 
     75 
     76 // maximum value of an array
     77 jStat.max = function max(arr) {
     78   var high = arr[0];
     79   var i = 0;
     80   while (++i < arr.length)
     81     if (arr[i] > high)
     82       high = arr[i];
     83   return high;
     84 };
     85 
     86 
     87 // unique values of an array
     88 jStat.unique = function unique(arr) {
     89   var hash = {}, _arr = [];
     90   for(var i = 0; i < arr.length; i++) {
     91     if (!hash[arr[i]]) {
     92       hash[arr[i]] = true;
     93       _arr.push(arr[i]);
     94     }
     95   }
     96   return _arr;
     97 };
     98 
     99 
    100 // mean value of an array
    101 jStat.mean = function mean(arr) {
    102   return jStat.sum(arr) / arr.length;
    103 };
    104 
    105 
    106 // mean squared error (MSE)
    107 jStat.meansqerr = function meansqerr(arr) {
    108   return jStat.sumsqerr(arr) / arr.length;
    109 };
    110 
    111 
    112 // geometric mean of an array
    113 jStat.geomean = function geomean(arr) {
    114   var logs = arr.map(Math.log)
    115   var meanOfLogs = jStat.mean(logs)
    116   return Math.exp(meanOfLogs)
    117 };
    118 
    119 
    120 // median of an array
    121 jStat.median = function median(arr) {
    122   var arrlen = arr.length;
    123   var _arr = arr.slice().sort(ascNum);
    124   // check if array is even or odd, then return the appropriate
    125   return !(arrlen & 1)
    126     ? (_arr[(arrlen / 2) - 1 ] + _arr[(arrlen / 2)]) / 2
    127     : _arr[(arrlen / 2) | 0 ];
    128 };
    129 
    130 
    131 // cumulative sum of an array
    132 jStat.cumsum = function cumsum(arr) {
    133   return jStat.cumreduce(arr, function (a, b) { return a + b; });
    134 };
    135 
    136 
    137 // cumulative product of an array
    138 jStat.cumprod = function cumprod(arr) {
    139   return jStat.cumreduce(arr, function (a, b) { return a * b; });
    140 };
    141 
    142 
    143 // successive differences of a sequence
    144 jStat.diff = function diff(arr) {
    145   var diffs = [];
    146   var arrLen = arr.length;
    147   var i;
    148   for (i = 1; i < arrLen; i++)
    149     diffs.push(arr[i] - arr[i - 1]);
    150   return diffs;
    151 };
    152 
    153 
    154 // ranks of an array
    155 jStat.rank = function (arr) {
    156   var i;
    157   var distinctNumbers = [];
    158   var numberCounts = {};
    159   for (i = 0; i < arr.length; i++) {
    160     var number = arr[i];
    161     if (numberCounts[number]) {
    162       numberCounts[number]++;
    163     } else {
    164       numberCounts[number] = 1;
    165       distinctNumbers.push(number);
    166     }
    167   }
    168 
    169   var sortedDistinctNumbers = distinctNumbers.sort(ascNum);
    170   var numberRanks = {};
    171   var currentRank = 1;
    172   for (i = 0; i < sortedDistinctNumbers.length; i++) {
    173     var number = sortedDistinctNumbers[i];
    174     var count = numberCounts[number];
    175     var first = currentRank;
    176     var last = currentRank + count - 1;
    177     var rank = (first + last) / 2;
    178     numberRanks[number] = rank;
    179     currentRank += count;
    180   }
    181 
    182   return arr.map(function (number) {
    183     return numberRanks[number];
    184   });
    185 };
    186 
    187 
    188 // mode of an array
    189 // if there are multiple modes of an array, return all of them
    190 // is this the appropriate way of handling it?
    191 jStat.mode = function mode(arr) {
    192   var arrLen = arr.length;
    193   var _arr = arr.slice().sort(ascNum);
    194   var count = 1;
    195   var maxCount = 0;
    196   var numMaxCount = 0;
    197   var mode_arr = [];
    198   var i;
    199 
    200   for (i = 0; i < arrLen; i++) {
    201     if (_arr[i] === _arr[i + 1]) {
    202       count++;
    203     } else {
    204       if (count > maxCount) {
    205         mode_arr = [_arr[i]];
    206         maxCount = count;
    207         numMaxCount = 0;
    208       }
    209       // are there multiple max counts
    210       else if (count === maxCount) {
    211         mode_arr.push(_arr[i]);
    212         numMaxCount++;
    213       }
    214       // resetting count for new value in array
    215       count = 1;
    216     }
    217   }
    218 
    219   return numMaxCount === 0 ? mode_arr[0] : mode_arr;
    220 };
    221 
    222 
    223 // range of an array
    224 jStat.range = function range(arr) {
    225   return jStat.max(arr) - jStat.min(arr);
    226 };
    227 
    228 // variance of an array
    229 // flag = true indicates sample instead of population
    230 jStat.variance = function variance(arr, flag) {
    231   return jStat.sumsqerr(arr) / (arr.length - (flag ? 1 : 0));
    232 };
    233 
    234 // pooled variance of an array of arrays
    235 jStat.pooledvariance = function pooledvariance(arr) {
    236   var sumsqerr = arr.reduce(function (a, samples) {return a + jStat.sumsqerr(samples);}, 0);
    237   var count = arr.reduce(function (a, samples) {return a + samples.length;}, 0);
    238   return sumsqerr / (count - arr.length);
    239 };
    240 
    241 // deviation of an array
    242 jStat.deviation = function (arr) {
    243   var mean = jStat.mean(arr);
    244   var arrlen = arr.length;
    245   var dev = new Array(arrlen);
    246   for (var i = 0; i < arrlen; i++) {
    247     dev[i] = arr[i] - mean;
    248   }
    249   return dev;
    250 };
    251 
    252 // standard deviation of an array
    253 // flag = true indicates sample instead of population
    254 jStat.stdev = function stdev(arr, flag) {
    255   return Math.sqrt(jStat.variance(arr, flag));
    256 };
    257 
    258 // pooled standard deviation of an array of arrays
    259 jStat.pooledstdev = function pooledstdev(arr) {
    260   return Math.sqrt(jStat.pooledvariance(arr));
    261 };
    262 
    263 // mean deviation (mean absolute deviation) of an array
    264 jStat.meandev = function meandev(arr) {
    265   var mean = jStat.mean(arr);
    266   var a = [];
    267   for (var i = arr.length - 1; i >= 0; i--) {
    268     a.push(Math.abs(arr[i] - mean));
    269   }
    270   return jStat.mean(a);
    271 };
    272 
    273 
    274 // median deviation (median absolute deviation) of an array
    275 jStat.meddev = function meddev(arr) {
    276   var median = jStat.median(arr);
    277   var a = [];
    278   for (var i = arr.length - 1; i >= 0; i--) {
    279     a.push(Math.abs(arr[i] - median));
    280   }
    281   return jStat.median(a);
    282 };
    283 
    284 
    285 // coefficient of variation
    286 jStat.coeffvar = function coeffvar(arr) {
    287   return jStat.stdev(arr) / jStat.mean(arr);
    288 };
    289 
    290 
    291 // quartiles of an array
    292 jStat.quartiles = function quartiles(arr) {
    293   var arrlen = arr.length;
    294   var _arr = arr.slice().sort(ascNum);
    295   return [
    296     _arr[ Math.round((arrlen) / 4) - 1 ],
    297     _arr[ Math.round((arrlen) / 2) - 1 ],
    298     _arr[ Math.round((arrlen) * 3 / 4) - 1 ]
    299   ];
    300 };
    301 
    302 
    303 // Arbitary quantiles of an array. Direct port of the scipy.stats
    304 // implementation by Pierre GF Gerard-Marchant.
    305 jStat.quantiles = function quantiles(arr, quantilesArray, alphap, betap) {
    306   var sortedArray = arr.slice().sort(ascNum);
    307   var quantileVals = [quantilesArray.length];
    308   var n = arr.length;
    309   var i, p, m, aleph, k, gamma;
    310 
    311   if (typeof alphap === 'undefined')
    312     alphap = 3 / 8;
    313   if (typeof betap === 'undefined')
    314     betap = 3 / 8;
    315 
    316   for (i = 0; i < quantilesArray.length; i++) {
    317     p = quantilesArray[i];
    318     m = alphap + p * (1 - alphap - betap);
    319     aleph = n * p + m;
    320     k = Math.floor(clip(aleph, 1, n - 1));
    321     gamma = clip(aleph - k, 0, 1);
    322     quantileVals[i] = (1 - gamma) * sortedArray[k - 1] + gamma * sortedArray[k];
    323   }
    324 
    325   return quantileVals;
    326 };
    327 
    328 // Return the k-th percentile of values in a range, where k is in the range 0..1, inclusive.
    329 // Passing true for the exclusive parameter excludes both endpoints of the range.
    330 jStat.percentile = function percentile(arr, k, exclusive) {
    331   var _arr = arr.slice().sort(ascNum);
    332   var realIndex = k * (_arr.length + (exclusive ? 1 : -1)) + (exclusive ? 0 : 1);
    333   var index = parseInt(realIndex);
    334   var frac = realIndex - index;
    335   if (index + 1 < _arr.length) {
    336     return _arr[index - 1] + frac * (_arr[index] - _arr[index - 1]);
    337   } else {
    338     return _arr[index - 1];
    339   }
    340 }
    341 
    342 // The percentile rank of score in a given array. Returns the percentage
    343 // of all values in the input array that are less than (kind='strict') or
    344 // less or equal than (kind='weak') score. Default is weak.
    345 jStat.percentileOfScore = function percentileOfScore(arr, score, kind) {
    346   var counter = 0;
    347   var len = arr.length;
    348   var strict = false;
    349   var value, i;
    350 
    351   if (kind === 'strict')
    352     strict = true;
    353 
    354   for (i = 0; i < len; i++) {
    355     value = arr[i];
    356     if ((strict && value < score) ||
    357         (!strict && value <= score)) {
    358       counter++;
    359     }
    360   }
    361 
    362   return counter / len;
    363 };
    364 
    365 
    366 // Histogram (bin count) data
    367 jStat.histogram = function histogram(arr, binCnt) {
    368   binCnt = binCnt || 4;
    369   var first = jStat.min(arr);
    370   var binWidth = (jStat.max(arr) - first) / binCnt;
    371   var len = arr.length;
    372   var bins = [];
    373   var i;
    374 
    375   for (i = 0; i < binCnt; i++)
    376     bins[i] = 0;
    377   for (i = 0; i < len; i++)
    378     bins[Math.min(Math.floor(((arr[i] - first) / binWidth)), binCnt - 1)] += 1;
    379 
    380   return bins;
    381 };
    382 
    383 
    384 // covariance of two arrays
    385 jStat.covariance = function covariance(arr1, arr2) {
    386   var u = jStat.mean(arr1);
    387   var v = jStat.mean(arr2);
    388   var arr1Len = arr1.length;
    389   var sq_dev = new Array(arr1Len);
    390   var i;
    391 
    392   for (i = 0; i < arr1Len; i++)
    393     sq_dev[i] = (arr1[i] - u) * (arr2[i] - v);
    394 
    395   return jStat.sum(sq_dev) / (arr1Len - 1);
    396 };
    397 
    398 
    399 // (pearson's) population correlation coefficient, rho
    400 jStat.corrcoeff = function corrcoeff(arr1, arr2) {
    401   return jStat.covariance(arr1, arr2) /
    402       jStat.stdev(arr1, 1) /
    403       jStat.stdev(arr2, 1);
    404 };
    405 
    406   // (spearman's) rank correlation coefficient, sp
    407 jStat.spearmancoeff =  function (arr1, arr2) {
    408   arr1 = jStat.rank(arr1);
    409   arr2 = jStat.rank(arr2);
    410   //return pearson's correlation of the ranks:
    411   return jStat.corrcoeff(arr1, arr2);
    412 }
    413 
    414 
    415 // statistical standardized moments (general form of skew/kurt)
    416 jStat.stanMoment = function stanMoment(arr, n) {
    417   var mu = jStat.mean(arr);
    418   var sigma = jStat.stdev(arr);
    419   var len = arr.length;
    420   var skewSum = 0;
    421 
    422   for (var i = 0; i < len; i++)
    423     skewSum += Math.pow((arr[i] - mu) / sigma, n);
    424 
    425   return skewSum / arr.length;
    426 };
    427 
    428 // (pearson's) moment coefficient of skewness
    429 jStat.skewness = function skewness(arr) {
    430   return jStat.stanMoment(arr, 3);
    431 };
    432 
    433 // (pearson's) (excess) kurtosis
    434 jStat.kurtosis = function kurtosis(arr) {
    435   return jStat.stanMoment(arr, 4) - 3;
    436 };
    437 
    438 
    439 var jProto = jStat.prototype;
    440 
    441 
    442 // Extend jProto with method for calculating cumulative sums and products.
    443 // This differs from the similar extension below as cumsum and cumprod should
    444 // not be run again in the case fullbool === true.
    445 // If a matrix is passed, automatically assume operation should be done on the
    446 // columns.
    447 (function(funcs) {
    448   for (var i = 0; i < funcs.length; i++) (function(passfunc) {
    449     // If a matrix is passed, automatically assume operation should be done on
    450     // the columns.
    451     jProto[passfunc] = function(fullbool, func) {
    452       var arr = [];
    453       var i = 0;
    454       var tmpthis = this;
    455       // Assignment reassignation depending on how parameters were passed in.
    456       if (isFunction(fullbool)) {
    457         func = fullbool;
    458         fullbool = false;
    459       }
    460       // Check if a callback was passed with the function.
    461       if (func) {
    462         setTimeout(function() {
    463           func.call(tmpthis, jProto[passfunc].call(tmpthis, fullbool));
    464         });
    465         return this;
    466       }
    467       // Check if matrix and run calculations.
    468       if (this.length > 1) {
    469         tmpthis = fullbool === true ? this : this.transpose();
    470         for (; i < tmpthis.length; i++)
    471           arr[i] = jStat[passfunc](tmpthis[i]);
    472         return arr;
    473       }
    474       // Pass fullbool if only vector, not a matrix. for variance and stdev.
    475       return jStat[passfunc](this[0], fullbool);
    476     };
    477   })(funcs[i]);
    478 })(('cumsum cumprod').split(' '));
    479 
    480 
    481 // Extend jProto with methods which don't require arguments and work on columns.
    482 (function(funcs) {
    483   for (var i = 0; i < funcs.length; i++) (function(passfunc) {
    484     // If a matrix is passed, automatically assume operation should be done on
    485     // the columns.
    486     jProto[passfunc] = function(fullbool, func) {
    487       var arr = [];
    488       var i = 0;
    489       var tmpthis = this;
    490       // Assignment reassignation depending on how parameters were passed in.
    491       if (isFunction(fullbool)) {
    492         func = fullbool;
    493         fullbool = false;
    494       }
    495       // Check if a callback was passed with the function.
    496       if (func) {
    497         setTimeout(function() {
    498           func.call(tmpthis, jProto[passfunc].call(tmpthis, fullbool));
    499         });
    500         return this;
    501       }
    502       // Check if matrix and run calculations.
    503       if (this.length > 1) {
    504         if (passfunc !== 'sumrow')
    505           tmpthis = fullbool === true ? this : this.transpose();
    506         for (; i < tmpthis.length; i++)
    507           arr[i] = jStat[passfunc](tmpthis[i]);
    508         return fullbool === true
    509             ? jStat[passfunc](jStat.utils.toVector(arr))
    510             : arr;
    511       }
    512       // Pass fullbool if only vector, not a matrix. for variance and stdev.
    513       return jStat[passfunc](this[0], fullbool);
    514     };
    515   })(funcs[i]);
    516 })(('sum sumsqrd sumsqerr sumrow product min max unique mean meansqerr ' +
    517     'geomean median diff rank mode range variance deviation stdev meandev ' +
    518     'meddev coeffvar quartiles histogram skewness kurtosis').split(' '));
    519 
    520 
    521 // Extend jProto with functions that take arguments. Operations on matrices are
    522 // done on columns.
    523 (function(funcs) {
    524   for (var i = 0; i < funcs.length; i++) (function(passfunc) {
    525     jProto[passfunc] = function() {
    526       var arr = [];
    527       var i = 0;
    528       var tmpthis = this;
    529       var args = Array.prototype.slice.call(arguments);
    530       var callbackFunction;
    531 
    532       // If the last argument is a function, we assume it's a callback; we
    533       // strip the callback out and call the function again.
    534       if (isFunction(args[args.length - 1])) {
    535         callbackFunction = args[args.length - 1];
    536         var argsToPass = args.slice(0, args.length - 1);
    537 
    538         setTimeout(function() {
    539           callbackFunction.call(tmpthis,
    540                                 jProto[passfunc].apply(tmpthis, argsToPass));
    541         });
    542         return this;
    543 
    544       // Otherwise we curry the function args and call normally.
    545       } else {
    546         callbackFunction = undefined;
    547         var curriedFunction = function curriedFunction(vector) {
    548           return jStat[passfunc].apply(tmpthis, [vector].concat(args));
    549         }
    550       }
    551 
    552       // If this is a matrix, run column-by-column.
    553       if (this.length > 1) {
    554         tmpthis = tmpthis.transpose();
    555         for (; i < tmpthis.length; i++)
    556           arr[i] = curriedFunction(tmpthis[i]);
    557         return arr;
    558       }
    559 
    560       // Otherwise run on the vector.
    561       return curriedFunction(this[0]);
    562     };
    563   })(funcs[i]);
    564 })('quantiles percentileOfScore'.split(' '));
    565 
    566 }(jStat, Math));