Instantly share code, notes, and snippets.

Embed
What would you like to do?
Pearson Correlation (JavaScript)
/**
* @fileoverview Pearson correlation score algorithm.
* @author matt.west@kojilabs.com (Matt West)
* @license Copyright 2013 Matt West.
* Licensed under MIT (http://opensource.org/licenses/MIT).
*/
/**
* Calculate the person correlation score between two items in a dataset.
*
* @param {object} prefs The dataset containing data about both items that
* are being compared.
* @param {string} p1 Item one for comparison.
* @param {string} p2 Item two for comparison.
* @return {float} The pearson correlation score.
*/
function pearsonCorrelation(prefs, p1, p2) {
var si = [];
for (var key in prefs[p1]) {
if (prefs[p2][key]) si.push(key);
}
var n = si.length;
if (n == 0) return 0;
var sum1 = 0;
for (var i = 0; i < si.length; i++) sum1 += prefs[p1][si[i]];
var sum2 = 0;
for (var i = 0; i < si.length; i++) sum2 += prefs[p2][si[i]];
var sum1Sq = 0;
for (var i = 0; i < si.length; i++) {
sum1Sq += Math.pow(prefs[p1][si[i]], 2);
}
var sum2Sq = 0;
for (var i = 0; i < si.length; i++) {
sum2Sq += Math.pow(prefs[p2][si[i]], 2);
}
var pSum = 0;
for (var i = 0; i < si.length; i++) {
pSum += prefs[p1][si[i]] * prefs[p2][si[i]];
}
var num = pSum - (sum1 * sum2 / n);
var den = Math.sqrt((sum1Sq - Math.pow(sum1, 2) / n) *
(sum2Sq - Math.pow(sum2, 2) / n));
if (den == 0) return 0;
return num / den;
}
@sash108

This comment has been minimized.

Copy link

sash108 commented May 27, 2015

could you give one example please for it with example dataset?

@antonioaltamura

This comment has been minimized.

Copy link

antonioaltamura commented Aug 29, 2015

If you still need it :)

var data = new Array(
                    new Array(21,54,60,78,82),
                    new Array(20,54,54,65,45)
        );
console.log(pearsonCorrelation(data,0,1))

please note the function works with qualitative distributions too (associative array)

@kdamar3

This comment has been minimized.

Copy link

kdamar3 commented May 18, 2017

Hi there, i used ur library just lazy to write one...i got a pearson relation as NaN for some huge dataset arrays. i tried writing a new code ..then got the actual value.

i have one array with values like 0.4554 of more than 20,000 rows and another with values like 20. as it is big file, i cannot link it here but just want to bring to ur attention.

@nahidakbar

This comment has been minimized.

Copy link

nahidakbar commented Jul 21, 2017

function pearson(values) {
const n = values.length;

if (n == 0) return 0;

let meanX = 0;
let meanY = 0;
for (var i = 0; i < n; i++) {
meanX += values[i].x / n
meanY += values[i].y / n
}

let num = 0;
let den1 = 0;
let den2 = 0;

for (var i = 0; i < n; i++) {
let dx = (values[i].x - meanX);
let dy = (values[i].y - meanY);
num += dx * dy
den1 += dx * dx
den2 += dy * dy
}

const den = Math.sqrt(den1) * Math.sqrt(den2);

if (den == 0) return 0;

return num / den;
}

pearson([{x: 0, y: 0}, {x:1, y:1}])

@LtHelo

This comment has been minimized.

Copy link

LtHelo commented Jun 7, 2018

thank u ,i just need this

@comfuture

This comment has been minimized.

Copy link

comfuture commented Oct 26, 2018

I've rewrote this function in es6.
The code is more concise, but it does not work with associative arrays that were possible in the original code.

/**
 * calculates pearson correlation
 * @param {number[]} d1
 * @param {number[]} d2
 */
export function corr(d1, d2) {
  let { min, pow, sqrt } = Math
  let add = (a, b) => a + b
  let n = min(d1.length, d2.length)
  if (n === 0) {
    return 0
  }
  [d1, d2] = [d1.slice(0, n), d2.slice(0, n)]
  let [sum1, sum2] = [d1, d2].map(l => l.reduce(add))
  let [pow1, pow2] = [d1, d2].map(l => l.reduce((a, b) => a + pow(b, 2), 0))
  let mulSum = d1.map((n, i) => n * d2[i]).reduce(add)
  let dense = sqrt((pow1 - pow(sum1, 2) / n) * (pow2 - pow(sum2, 2) / n))
  if (dense === 0) {
    return 0
  }
  return (mulSum - (sum1 * sum2 / n)) / dense
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment