simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

variance.js (6110B)


      1 "use strict";
      2 
      3 Object.defineProperty(exports, "__esModule", {
      4   value: true
      5 });
      6 exports.createVariance = void 0;
      7 
      8 var _collection = require("../../utils/collection.js");
      9 
     10 var _is = require("../../utils/is.js");
     11 
     12 var _factory = require("../../utils/factory.js");
     13 
     14 var _improveErrorMessage = require("./utils/improveErrorMessage.js");
     15 
     16 var DEFAULT_NORMALIZATION = 'unbiased';
     17 var name = 'variance';
     18 var dependencies = ['typed', 'add', 'subtract', 'multiply', 'divide', 'apply', 'isNaN'];
     19 var createVariance = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) {
     20   var typed = _ref.typed,
     21       add = _ref.add,
     22       subtract = _ref.subtract,
     23       multiply = _ref.multiply,
     24       divide = _ref.divide,
     25       apply = _ref.apply,
     26       isNaN = _ref.isNaN;
     27 
     28   /**
     29    * Compute the variance of a matrix or a  list with values.
     30    * In case of a (multi dimensional) array or matrix, the variance over all
     31    * elements will be calculated.
     32    *
     33    * Additionally, it is possible to compute the variance along the rows
     34    * or columns of a matrix by specifying the dimension as the second argument.
     35    *
     36    * Optionally, the type of normalization can be specified as the final
     37    * parameter. The parameter `normalization` can be one of the following values:
     38    *
     39    * - 'unbiased' (default) The sum of squared errors is divided by (n - 1)
     40    * - 'uncorrected'        The sum of squared errors is divided by n
     41    * - 'biased'             The sum of squared errors is divided by (n + 1)
     42    *
     43    *
     44    * Note that older browser may not like the variable name `var`. In that
     45    * case, the function can be called as `math['var'](...)` instead of
     46    * `math.var(...)`.
     47    *
     48    * Syntax:
     49    *
     50    *     math.variance(a, b, c, ...)
     51    *     math.variance(A)
     52    *     math.variance(A, normalization)
     53    *     math.variance(A, dimension)
     54    *     math.variance(A, dimension, normalization)
     55    *
     56    * Examples:
     57    *
     58    *     math.variance(2, 4, 6)                     // returns 4
     59    *     math.variance([2, 4, 6, 8])                // returns 6.666666666666667
     60    *     math.variance([2, 4, 6, 8], 'uncorrected') // returns 5
     61    *     math.variance([2, 4, 6, 8], 'biased')      // returns 4
     62    *
     63    *     math.variance([[1, 2, 3], [4, 5, 6]])      // returns 3.5
     64    *     math.variance([[1, 2, 3], [4, 6, 8]], 0)   // returns [4.5, 8, 12.5]
     65    *     math.variance([[1, 2, 3], [4, 6, 8]], 1)   // returns [1, 4]
     66    *     math.variance([[1, 2, 3], [4, 6, 8]], 1, 'biased') // returns [0.5, 2]
     67    *
     68    * See also:
     69    *
     70    *    mean, median, max, min, prod, std, sum
     71    *
     72    * @param {Array | Matrix} array
     73    *                        A single matrix or or multiple scalar values
     74    * @param {string} [normalization='unbiased']
     75    *                        Determines how to normalize the variance.
     76    *                        Choose 'unbiased' (default), 'uncorrected', or 'biased'.
     77    * @param dimension {number | BigNumber}
     78    *                        Determines the axis to compute the variance for a matrix
     79    * @return {*} The variance
     80    */
     81   return typed(name, {
     82     // variance([a, b, c, d, ...])
     83     'Array | Matrix': function ArrayMatrix(array) {
     84       return _var(array, DEFAULT_NORMALIZATION);
     85     },
     86     // variance([a, b, c, d, ...], normalization)
     87     'Array | Matrix, string': _var,
     88     // variance([a, b, c, c, ...], dim)
     89     'Array | Matrix, number | BigNumber': function ArrayMatrixNumberBigNumber(array, dim) {
     90       return _varDim(array, dim, DEFAULT_NORMALIZATION);
     91     },
     92     // variance([a, b, c, c, ...], dim, normalization)
     93     'Array | Matrix, number | BigNumber, string': _varDim,
     94     // variance(a, b, c, d, ...)
     95     '...': function _(args) {
     96       return _var(args, DEFAULT_NORMALIZATION);
     97     }
     98   });
     99   /**
    100    * Recursively calculate the variance of an n-dimensional array
    101    * @param {Array} array
    102    * @param {string} normalization
    103    *                        Determines how to normalize the variance:
    104    *                        - 'unbiased'    The sum of squared errors is divided by (n - 1)
    105    *                        - 'uncorrected' The sum of squared errors is divided by n
    106    *                        - 'biased'      The sum of squared errors is divided by (n + 1)
    107    * @return {number | BigNumber} variance
    108    * @private
    109    */
    110 
    111   function _var(array, normalization) {
    112     var sum;
    113     var num = 0;
    114 
    115     if (array.length === 0) {
    116       throw new SyntaxError('Function variance requires one or more parameters (0 provided)');
    117     } // calculate the mean and number of elements
    118 
    119 
    120     (0, _collection.deepForEach)(array, function (value) {
    121       try {
    122         sum = sum === undefined ? value : add(sum, value);
    123         num++;
    124       } catch (err) {
    125         throw (0, _improveErrorMessage.improveErrorMessage)(err, 'variance', value);
    126       }
    127     });
    128     if (num === 0) throw new Error('Cannot calculate variance of an empty array');
    129     var mean = divide(sum, num); // calculate the variance
    130 
    131     sum = undefined;
    132     (0, _collection.deepForEach)(array, function (value) {
    133       var diff = subtract(value, mean);
    134       sum = sum === undefined ? multiply(diff, diff) : add(sum, multiply(diff, diff));
    135     });
    136 
    137     if (isNaN(sum)) {
    138       return sum;
    139     }
    140 
    141     switch (normalization) {
    142       case 'uncorrected':
    143         return divide(sum, num);
    144 
    145       case 'biased':
    146         return divide(sum, num + 1);
    147 
    148       case 'unbiased':
    149         {
    150           var zero = (0, _is.isBigNumber)(sum) ? sum.mul(0) : 0;
    151           return num === 1 ? zero : divide(sum, num - 1);
    152         }
    153 
    154       default:
    155         throw new Error('Unknown normalization "' + normalization + '". ' + 'Choose "unbiased" (default), "uncorrected", or "biased".');
    156     }
    157   }
    158 
    159   function _varDim(array, dim, normalization) {
    160     try {
    161       if (array.length === 0) {
    162         throw new SyntaxError('Function variance requires one or more parameters (0 provided)');
    163       }
    164 
    165       return apply(array, dim, function (x) {
    166         return _var(x, normalization);
    167       });
    168     } catch (err) {
    169       throw (0, _improveErrorMessage.improveErrorMessage)(err, 'variance');
    170     }
    171   }
    172 });
    173 exports.createVariance = createVariance;