Home

Node Stats Helpers

Build Status Coverage Status Active Development

This is a library that helps with some common stats operations. We support the following:

  • Combinations
    • Counting number of combinations
    • Getting an array of k-combinations
    • Getting all power sets
  • Permutations
    • Counting number of permutations
    • Getting an array of k-permutations
    • Getting an array of all permutations
  • Statical Calculation
    • Mean, Median, Mode
    • Geometric means
    • Standard deviation (sample or population)
    • Z-Score from mean/standard deviation or input
    • Correlation
  • Z-score table (From -3.99 to 3.99)
  • Simple probability calculations
  • Matrix Operations
    • Determinant
    • Matrix of Minors, Cofactors
    • Matrix Transpose
    • Matrix Inverse
    • Row Canonical Form (Reduced Row Echelon Form)
    • Matrix Rank
    • LU Decomposition
    • QR Decomposition
    • Dot product
    • Arithmetic on every matrix element
    • Deep copying a matrix
    • Random or Identity matrix of a given size

Full Docs can be found at our git pages. Example usages are as followed.

Importing

The libraries can be imported using the following.

const {matrixLib, probabilityLib, statsLib, combinationLib, permutationLib} = require('../index.js');

Matrix Helper

Note that all matrixLib operations work on a duplicated copy of the matrix, the original reference is always maintained.

Adding a constant to every matrix element

Returns a matrix with the each constant C added to each element. In this example, c = 3

t = [[1,2,3], [1,2,3], [1,2,3]]
console.log(matrixLib.addMatrixC(t,3))
//=> [ [ 4, 5, 6 ], [ 4, 5, 6 ], [ 4, 5, 6 ] ]

Subtracting a constant to every matrix element

Returns a matrix with the each constant C subtracted from each element. In this example, c = 3

t = [[1,2,3], [1,2,3], [1,2,3]]
console.log(matrixLib.addMatrixC(t,3))
//=> [ [ -2, -1, 0 ], [ -2, -1, 0 ], [ -2, -1, 0 ] ]

Multiplying a constant to every matrix element

Returns a matrix with the each constant c multiplied to each element. In this example, c = 3

let matTest = [[1.00002,2.31,3,4,5], [-1,-10.4,1,1,5], [7,-8,1,2,8], [9,-1.1231,1,2,3]];
console.log(matrixLib.roundMatrix(matTest))
//=> [ [ 3, 6, 9 ], [ 3, 6, 9 ], [ 3, 6, 9 ] ]

Dividing a constant to every matrix element

Returns a matrix with each element divided by constant c. In this example, c = 3

t = [[3,6,9], [12,15,18], [21,24,27]]
console.log(matrixLib.divideMatrixC(t,3))
//=> [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]

Getting basic matricies

Get an identity matrix

console.log(matrixLib.getIdentityMatrix(3))
//=> [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ]

Get an identity matrix, but with extra columns of rows

console.log(matrixLib.getIdentityMatrixRC(4, 3))
//=> [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ], [ 0, 0, 0 ] ]

Get an matrix of constants (3X2 matrix of constantly 4)

console.log(matrixLib.getMatrix(3, 2, 4))
//=> [ [ 4, 4 ], [ 4, 4 ], [ 4, 4 ] ]

Basic Matrix operations

Comparing 2 matricies

let A = [1,2,3]
console.log(matrixLib.areMatriciesEqual(A, A)
//=> true
console.log(matrixLib.areMatriciesEqual(A, [[1,2],[2,3]])
//=> false

Comparing 2 matricies, with an error tolerance. By default tolerance is 0.1 set it using the third parameter.

let A = [1,2,3]
console.log(matrixLib.areMatriciesApproximatelyEqual(A, A))
//=> true
console.log(matrixLib.areMatriciesApproximatelyEqual(A, [1.09,2.01,3]))
//=> true
console.log(matrixLib.areMatriciesApproximatelyEqual(A, [1.09,2.01,3], 0.05))
//=> false

Duplicating a matrix - leaves original reference intact

let A = [1,2,3]
console.log(matrixLib.duplicateMatrix(A))
//=> [1,2,3]

Get an random matrix (4X3 matrix between -10 and 10, floats allowed)

matrixLib.getRandomMatrix(4, 3, {min:-10, max:10 , intOnly: false}):

Matrix Transpose

console.log(matrixLib.transposeMatrix([1,2,3]));
//=> [ [ 1 ], [ 2 ], [ 3 ] ]

Rounding every matrix element

Rounds each matrix element to a given decimal place, in this case, rounds to first decimal

t = [[1,2,3], [1,2,3], [1,2,3]]
console.log(matrixLib.roundMatrix(matTest, 1))
//=> [
//    [ 1, 2.3, 3, 4, 5 ],
//    [ -1, -10.4, 1, 1, 5 ],
//    [ 7, -8, 1, 2, 8 ],
//    [ 9, -1.1, 1, 2, 3 ]
//   ]

Matrix dot product

Returns a matrix that represents the dot product of the 2 input matricies

t = [
    [1,2,3],
    [4,5,6],
    [7,2,9]
]

t2 = [
    [1,1,1],
    [1,1,1],
    [1,1,1]
]
console.log(matrixLib.multiplyMatrix(t, t2));
//=> [ [ 6, 6, 6 ], [ 15, 15, 15 ], [ 18, 18, 18 ] ]

LU Decomposition

Returns a lower and upper matrix decomposed from the given matrix. Utilizes Crout's method Returns null if the determinant is too close to 0 (No LU available)

let matTest = [[1.00002,2.31,3,4,5], [-1,-10.4,1,1,5], [7,-8,1,2,8], [9,-1.1231,1,2,3]];
console.log(matrixLib.QrDecomposeMatrix(matTest));


//=> {
//     L: [
//       [ -3, 0, 0 ],
//       [ -12, -5.8, 0 ],
//       [ 77, 19.633333333333333, -11.16896551724139 ]
//     ],
//     U: [
//       [ 1, -0.5666666666666667, 3 ],
//       [ 0, 1, -6.1034482758620685 ],
//       [ 0, 0, 1 ]
//     ]
//   }

QR Decomposition

Performs householder's algorithm to QR decompose the matrix. returns a dictionary with { Q: R: Q_x: <Intermediate H matricies, starting from H0...Hx> }

let matTest = [[1.00002,2.31,3,4,5], [-1,-10.4,1,1,5], [7,-8,1,2,8], [9,-1.1231,1,2,3]];
let qrRes = matrixLib.QrDecomposeMatrix(matTest);
console.log(matrixLib.roundMatrix(qrRes.R));
//=> [
//     [ 11, -5, 2, 3, 7 ],
//     [ 0, 13, -0, -0, -6 ],
//     [ -0, 0, 3, 4, 6 ],
//     [ 0, -0, 0, 0, 2 ]
//   ]
console.log(matrixLib.roundMatrix(qrRes.Q));
//=> [
//     [ 0, 0, 1, 0 ],
//     [ -0, -1, 0, -0 ],
//     [ 1, -0, -0, 1 ],
//     [ 1, 0, -0, -1 ]
//   ]
console.log(qrRes.Q_x)
//=> [
//     [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
//     [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ]
//   ]

Determinant

Returns the determinant of the matrix

test = [[1,2,3], [4,5,6], [7,2,9]]
console.log(matrixLib.determinantMatrix(test));
//=> -36

Inverse of a matrix

Returns the inverse of the matrix

test = [[1,2,3], [4,5,6], [7,2,9]]
console.log(matrixLib.inverseMatrix(test));
//=> [
//    [ -0.9166666666666666, 0.3333333333333333, 0.08333333333333333 ],  
//    [ -0.16666666666666666, 0.3333333333333333, -0.16666666666666666 ],
//    [ 0.75, -0.3333333333333333, 0.08333333333333333 ]
//   ]

Matrix of Cofactors

Puts the matrix as a matrix of cofactors

let coFactorTest = [[1,2,3, 11],[4,-2,13, -6],[-7, 9,8,7]];
console.log(matrixLib.cofactorMatrix(coFactorTest));
// => [
//      [ 1, -2, 3, -11 ],
//      [ -4, -2, -13, -6 ],
//      [ -7, -9, 8, -7 ]
//    ]

Matrix of Minors

Puts the matrix as a matrix of minors, matrix must be Square.

let coFactorTest = [[1,2,3, 11],[4,-2,13, -6],[-7, 9,8,7]];
console.log(matrixLib.cofactorMatrix(coFactorTest));
// => [
//      [ -133, 123, 22, 22 ],
//      [ -11, 29, 23, 23 ],
//      [ 32, 1, -10, -10 ]
//    ]

Eigenvalues of a matrix

Returns the eigenvalues of a matrix, all eigenvalues appears on the diagonal. In this case, the matrix eigenvalues are 4 and -3.

The second paramter can be used to control the maximum number of QR iteration algorithms cycles. The default is 20.

let mat2 = [[3,2],[3,-2]];
console.log(matrixLib.QReig(mat2));
//=> [
       [ 4.001464871443321, 0 ],
       [ 0, -3.0014648714433183 ]
     ]

console.log(matrixLib.QReig(mat2,2000));
//=> [
       [ 4.000000007324081, 0 ],
       [ 0, -3.000000007324077 ]
     ]

Eigenvectors of a matrix and given eigenvalue

Given a Square matrix and an approximate eigenvalue. A corresponding eigenvector is returned. The initial eigenvalue must be different than the actual eigenvalue - otherwise it may return NaN or Inifinty

This is based off of the inverse iteration algorithm.

In the following example, the eigenvalues are 4,-3 (as found previously). 2 is passed in as the initial eigenvalue.

The initial eigenvector is null (a random eigenvector is generated). By default - the iteration tolerance is 0, a maximum of 200 cycles is perofmed.

let mat2 = [[3,2],[3,-2]];
console.log(matrixLib.matrixEigenVector(mat2, 2));
// => [ [ 2 ], [ 1 ] ]

In the following example, the eigenvalues are 4,-3 (as found previously). -22 is passed in as the initial eigenvalue and [[-10],[-2]] is the initial eigenvector guess.

The algorithm parameters are 2000 cycles maximum or 0 change between each successive iterations

let mat2 = [[3,2],[3,-2]];
console.log(matrixLib.matrixEigenVector(mat2, -22, [[-10],[-2]], {tol = 0, iter=2000}));
// => [ [ -0.33333333333333337 ], [ 1 ] ]

Row Canonical Form and Rank

Puts the matrix in row canonical form (Reduced Row Echelon Form).

let rankTest = [[1,2,3, 11],[4,-2,13, -6],[-7, 9,8,7]];
console.log(matrixLib.rowCanonicalMatrix(rankTest));
// => [
//     [ 1, 0, 0, 4.169329073482428 ],
//     [ 0, 1, 0, 4.900958466453674 ],
//     [ 0, 0, 1, -0.9904153354632588 ]
//    ]

Finds the rank of the matrix

console.log(matrixLib.rankOfMatrix(rankTest));
// => 3

Combination Helper

Counting number of combinations

Returns the number of pemutations of the given input. The following is 5 choose 3 (5C3) and 10 choose 7 (10C7).

console.log(combinationLib.countCombinations(5,3))
//=> 10
console.log(combinationLib.countCombinations(10,7))
//=> 120

Getting the combinations

Returns the combinations of the given input. This utilizes the Forward-Backward Algorithm for generating combinations.

console.log(combinationLib.combinations([1,2,3,4,5,6,7,8,9,10],7))
//=> [ Set { 1, 2, 3, 4, 5, 6, 7 },
//     Set { 1, 2, 3, 4, 5, 6, 8 },
//     Set { 1, 2, 3, 4, 5, 6, 9 },
//     Set { 1, 2, 3, 4, 5, 6, 10 },
//     Set { 1, 2, 3, 4, 5, 7, 8 },
//     Set { 1, 2, 3, 4, 5, 7, 9 },
//     ...119 more
console.log(combinationLib.combinations([1,2,3,4,5,6,7,8,9,10],7).length)
//=> 120

Counting number of power sets

Returns the number of combinations of the given input.

console.log(combinationLib.countPowerSet(6));
//=> 64

Getting the power sets

Returns the powersets of the given input.

console.log(combinationLib.powerSet([1,2,3,4,5]));
//=> [ Set {},
//     Set { 1 },
//     Set { 2 },
//     Set { 1, 2 }, 
//     Set { 3 }, 
//     Set { 1, 3 }, 
//     ...26 more

Permutation Helper

Factorials

Returns the evaluated factorial of the given input.

console.log(permutationLib.factorial(5));
//=> 120

Counting number of permutations

Returns the number of pemutations of the given input. The following is 5P5.

console.log(permutationLib.countPermutation(5,5))
//=> 120
console.log(permutationLib.countPermutation(5,1))
//=> 5

Getting the permutations

Returns the pemutations of the given input. This utilizes Heap's Algorithm for generating permutations.

console.log(permutationLib.permutation([1,2,3]))
//=> [ [ 1, 2, 3 ],
//     [ 2, 1, 3 ],
//     [ 3, 1, 2 ],
//     [ 1, 3, 2 ],
//     [ 2, 3, 1 ],
//     [ 3, 2, 1 ]
//   ]

Getting N permutations

Returns the N pemutations of the given input. This utilizes a recursive algorithm to generate all permutations of a given length. The Following is 3-length permutations of 5 (5P3).

console.log(permutationLib.kPermutations([1,2,3,4,5], 3))
//=> [ [ 1, 2, 3 ],
//     [ 1, 2, 4 ],
//     [ 1, 2, 5 ],
//     [ 1, 3, 2 ],
//     [ 1, 3, 4 ],
//     [ 1, 3, 5 ],
//     ...54 more
console.log(permutationLib.nPermutations([1,2,3,4,5], 3).length)
//=> 60

Probability Helper

P(X and Y)

Probability of X and Y occuring (Assuming X and Y are independent).

console.log(probabilityLib.XandY(0.5, 0.3))
//=> 0.15

P(X or Y)

Probability of X or Y occuring (Assuming X and Y are independent).

console.log(probabilityLib.XorY(0.5, 0.3))
//=> 0.65

P(X and ~Y)

Probability of X and NOT Y occuring (Assuming X and Y are independent).

console.log(probabilityLib.XandNotY(0.5, 0.3))
//=> 0.35

P(X | Y)

Probability of X occuring given that Y occured (Assuming X and Y are independent).

console.log(probabilityLib.XgivenY(0.5, 0.3))
//=> 0.5

P(X | ~Y)

Probability of X occuring given that Y DID NOT occured (Assuming X and Y are independent).

console.log(probabilityLib.XgivenNotY(0.5, 0.3))
//=> 0.5

Stats Helper

Sum of array

Returns a value representing the sum of the input array. Returns 0 if input is invalid.

console.log(statsLib.sum([1,2,3,4,5]));
//=> 15

Geometric sum of array

Returns a value representing the factorial of the input array. Returns 0 if input is invalid.

console.log(statsLib.geometricSum([1,2,3,4,5]));
//=> 120

Mean of array

Returns a value representing the factorial of the input array. Returns undefined if input is invalid.

console.log(statsLib.mean([1,2,3,4,5]));
//=> 3

Geometric mean of array

Returns a value representing the geometric mean of the input array. Returns undefined if input is invalid.

console.log(statsLib.geometricMean([1,2,3,4,5]));
//=> 2.605171084697352

Median of array

Returns a value representing the geometric mean of the input array. Returns NaN if input is invalid.

console.log(statsLib.median([1,2,3,4,5]));
//=> 3
console.log(statsLib.median([5,3,1,4,2,3,4,5]));
//=> 3.5

Mode of array

Returns a value representing the mode of the input array.

console.log(statsLib.mode([1,2,3,4,5]));
//=> [ 1, 2, 3, 4, 5 ]
console.log(statsLib.mode([5,3,1,4,2,3,4,5]));
//=> [ 3, 4, 5 ]
console.log(statsLib.mode([5,3,1,4,2,3,4,5,7,7,7]));
//=> [ 7 ]

Standard deviation of array

Returns a value representing the standard deviation of the input array. Assumes the input array is the population unless otherwise specified. Returns NaN if input is invalid.

console.log(statsLib.stdev([5,3,1,4,2,3,4,5,7,7,7], opt = {"population": true}));
//=> 1.966664332071267
console.log(statsLib.stdev([5,3,1,4,2,3,4,5,7,7,7], opt = {"population": false}));
//=> 2.062654952856986

Absolute percentile of array

Returns a value representing the given percentile of the input array. The following example gives the 80th percentile value - which is 5.

console.log(statsLib.absolutePercentile(80, [5,3,1,4,2,3,4,5,7,7,7]));
//=> 5

Z-score of an value, mean and standard deviation

Returns a value representing the percentile of a value and a given input. Value does not have to be in the input, a Z-score calculation and lookup occurs. Returns undefined if input is not a number.

console.log(statsLib.percentileFromMeanAndStdev(5, 5.5, 3));
//=> 0.43251
console.log(statsLib.percentileFromMeanAndStdev(5, 22, 1.3));
//=> 0.00003

Z-score of a value and array

Returns a value representing the Z-score of the input array.

console.log(statsLib.zScore(7, [5,3,1,4,2,3,4,5,7,7,7]));
//=> 1.3405254742109705
console.log(statsLib.zScore(10, [5,3,1,4,2,3,4,5,7,7,7]));
//=> 2.8659510138303506

Percentile given value and input array

Returns a value representing the Z-score of the mean and standard deviaiton. Returns undefined if input is not a number.

console.log(statsLib.percentile(13, [1,2,3,4,5,6,7,8,9,10], opt={"population": false}));
//=> 0.99343
console.log(statsLib.percentile(5, [1,2,3,4,5,6,7,8,9,10], opt={"population": true}));
//=> 0.43251
console.log(statsLib.percentile(5.5, [1,2,3,4,5,6,7,8,9,10], opt={"population": true}));
//=> 0.5

Z-score percentile

Returns a value representing the percentile of a given Z-score. Returns undefined if input is not a number.

console.log(statsLib.zScorePercentile(3.99));
//=> 0.99997
console.log(statsLib.zScorePercentile(-2.1));
//=> 0.01786

Correlations

Returns a value representing the correlatio between 2 arrays

console.log(statsLib.correlation([1,2,3,4,5], [1,2,3,4,5]))
//=> 1
console.log(statsLib.correlation([1,2,3,4,5], [-1,-2,-3,-4,-5]))
//=> -1
console.log(statsLib.correlation([1,4,9,5,3], [-1,-2,-3,-4,-5]))
//=> -0.266500895444513