Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added correlation function to statistics #3015

Merged
merged 9 commits into from
Sep 1, 2023
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -231,5 +231,6 @@ MaybePixem <47889538+MaybePixem@users.noreply.github.com>
Aly Khaled <alykhaled2001@live.com>
BuildTools <anikpatel1322@gmail.com>
Anik Patel <74193405+Bobingstern@users.noreply.github.com>
vrushaket <vrushu00@gmail.com>

# Generated by tools/update-authors.js
2 changes: 2 additions & 0 deletions src/expression/embeddedDocs/embeddedDocs.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ import { stdDocs } from './function/statistics/std.js'
import { cumSumDocs } from './function/statistics/cumsum.js'
import { sumDocs } from './function/statistics/sum.js'
import { varianceDocs } from './function/statistics/variance.js'
import { corrDocs } from './function/statistics/corr.js'
import { acosDocs } from './function/trigonometry/acos.js'
import { acoshDocs } from './function/trigonometry/acosh.js'
import { acotDocs } from './function/trigonometry/acot.js'
Expand Down Expand Up @@ -543,6 +544,7 @@ export const embeddedDocs = {
std: stdDocs,
sum: sumDocs,
variance: varianceDocs,
corr: corrDocs,

// functions - trigonometry
acos: acosDocs,
Expand Down
22 changes: 22 additions & 0 deletions src/expression/embeddedDocs/function/statistics/corr.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export const corrDocs = {
name: 'corr',
category: 'Statistics',
syntax: [
'corr(A,B)'
],
description: 'Compute the correlation coefficient of a two list with values, For matrices, the matrix correlation coefficient is calculated.',
examples: [
'corr([2, 4, 6, 8],[1, 2, 3, 6])',
'corr(matrix([[1, 2.2, 3, 4.8, 5], [1, 2, 3, 4, 5]]), matrix([[4, 5.3, 6.6, 7, 8], [1, 2, 3, 4, 5]]))'
],
seealso: [
'max',
'mean',
'min',
'median',
'min',
'prod',
'std',
'sum'
]
}
1 change: 1 addition & 0 deletions src/factoriesAny.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ export { createMad } from './function/statistics/mad.js'
export { createVariance } from './function/statistics/variance.js'
export { createQuantileSeq } from './function/statistics/quantileSeq.js'
export { createStd } from './function/statistics/std.js'
export { createCorr } from './function/statistics/corr.js'
export { createCombinations } from './function/probability/combinations.js'
export { createCombinationsWithRep } from './function/probability/combinationsWithRep.js'
export { createGamma } from './function/probability/gamma.js'
Expand Down
1 change: 1 addition & 0 deletions src/factoriesNumber.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ export { createMad } from './function/statistics/mad.js'
export { createVariance } from './function/statistics/variance.js'
export { createQuantileSeq } from './function/statistics/quantileSeq.js'
export { createStd } from './function/statistics/std.js'
export { createCorr } from './function/statistics/corr.js'

// string
export { createFormat } from './function/string/format.js'
Expand Down
64 changes: 64 additions & 0 deletions src/function/statistics/corr.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { factory } from '../../utils/factory.js'
const name = 'corr'
const dependencies = ['typed', 'matrix', 'mean', 'sqrt', 'sum', 'add', 'subtract', 'multiply', 'pow', 'divide']

export const createCorr = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, sqrt, sum, add, subtract, multiply, pow, divide }) => {
/**
* Compute the correlation coefficient of a two list with values, For matrices, the matrix correlation coefficient is calculated.
*
* Syntax:
*
* math.corr(A, B)
*
* Examples:
*
* math.corr([1, 2, 3, 4, 5], [4, 5, 6, 7, 8]) // returns 1
* math.corr([1, 2.2, 3, 4.8, 5], [4, 5.3, 6.6, 7, 8]) // returns 0.9569941688503644
* math.corr(math.matrix([[1, 2.2, 3, 4.8, 5], [1, 2, 3, 4, 5]]), math.matrix([[4, 5.3, 6.6, 7, 8], [1, 2, 3, 4, 5]])) // returns DenseMatrix [0.9569941688503644, 1]
*
* See also:
*
* median, mean, min, max, sum, prod, std, variance
*
* @param {Array | Matrix} A The first array or matrix to compute correlation coefficient
* @param {Array | Matrix} B The second array or matrix to compute correlation coefficient
* @return {*} The correlation coefficient
*/
return typed(name, {
'Array, Array': function (A, B) {
return _corr(A, B)
},
'Matrix, Matrix': function (xMatrix, yMatrix) {
return matrix(_corr(xMatrix.toArray(), yMatrix.toArray()))
}
})
/**
* Calculate the correlation coefficient between two arrays or matrices.
* @param {Array | Matrix} A
* @param {Array | Matrix} B
* @return {*} correlation coefficient
* @private
*/
function _corr (A, B) {
if (Array.isArray(A[0]) && Array.isArray(B[0])) {
const correlations = []
for (let i = 0; i < A.length; i++) {
correlations.push(correlation(A[i], B[i]))
}
return correlations
} else {
return correlation(A, B)
}
}
function correlation (A, B) {
const n = A.length
const sumX = sum(A)
const sumY = sum(B)
const sumXY = A.reduce((acc, x, index) => add(acc, multiply(x, B[index])), 0)
const sumXSquare = sum(A.map(x => pow(x, 2)))
const sumYSquare = sum(B.map(y => pow(y, 2)))
const numerator = subtract(multiply(n, sumXY), multiply(sumX, sumY))
const denominator = sqrt(multiply(subtract(multiply(n, sumXSquare), pow(sumX, 2)), subtract(multiply(n, sumYSquare), pow(sumY, 2))))
return divide(numerator, denominator)
}
})
21 changes: 21 additions & 0 deletions test/unit-tests/function/statistics/corr.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import assert from 'assert'
import math from '../../../../src/defaultInstance.js'
const corr = math.corr
const BigNumber = math.BigNumber

describe('correlation', function () {
it('should return the correlation coefficient from an array', function () {
assert.strictEqual(corr([new BigNumber(1), new BigNumber(2.2), new BigNumber(3), new BigNumber(4.8), new BigNumber(5)], [new BigNumber(4), new BigNumber(5.3), new BigNumber(6.6), new BigNumber(7), new BigNumber(8)]).toNumber(), 0.9569941688503653)
assert.strictEqual(corr([1, 2, 3, 4, 5], [4, 5, 6, 7, 8]), 1)
assert.strictEqual(corr([1, 2.2, 3, 4.8, 5], [4, 5.3, 6.6, 7, 8]), 0.9569941688503644)
assert.deepStrictEqual(corr(math.matrix([[1, 2.2, 3, 4.8, 5], [1, 2, 3, 4, 5]]), math.matrix([[4, 5.3, 6.6, 7, 8], [1, 2, 3, 4, 5]]))._data, [0.9569941688503644, 1])
})

it('should throw an error if called with invalid number of arguments', function () {
assert.throws(function () { corr() })
})

it('should throw an error if called with an empty array', function () {
assert.throws(function () { corr([]) })
})
})
8 changes: 8 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2970,6 +2970,14 @@ declare namespace math {
normalization: 'unbiased' | 'uncorrected' | 'biased'
): MathNumericType

/**
* Calculate the correlation coefficient between two matrix.
* @param {Array | Matrix} x The first array or matrix to compute correlation coefficient
* @param {Array | Matrix} y The second array or matrix to compute correlation coefficient
* @returns correlation coefficient
*/
corr(x: MathCollection, y: MathCollection): MathType

/*************************************************************************
* String functions
************************************************************************/
Expand Down