index.js

/**
 * Returns the covariance matrix for a given matrix.
 * @param {number[][]} x - A matrix where rows are samples and columns are variables.
 */
function cov(x) {
	// Useful variables
	N = x.length;

	// Step 1: Find expected value for each variable (columns are variables, rows are samples)
	E = [];
	for (var c = 0; c < x[0].length; c++) {
		u = 0;
		for (var r = 0; r < N; r++) {
			u += x[r][c];
		}
		E.push(u / N);
	}

	// Step 2: Center each variable at 0
	var centered = [];
	for (var r = 0; r < N; r++) {
		centered.push([]);
		for (var c = 0; c < x[0].length; c++) {
			centered[r].push(x[r][c] - E[c]);
		}
	}

	// Step 3: Calculate covariance between each possible combination of variables
	S = [];

	for (var i = 0; i < x[0].length; i++) {
		S.push([]);
	}

	for (var c1 = 0; c1 < x[0].length; c1++) {
		// Doing c2 = c1; because, for example, cov(1,2) = cov(2, 1)
		// so no need to recalculate
		for (var c2 = c1; c2 < x[0].length; c2++) {
			// Solve cov(c1, c2) = average of elementwise products of each variable sample
			var cov = 0;
			for (var r = 0; r < N; r++) {
				cov += centered[r][c1] * centered[r][c2];
			}
			cov /= (N - 1); // N-1 for sample covariance, N for population. In this case, using sample covariance
			S[c1][c2] = cov;
			S[c2][c1] = cov; // Matrix is symmetric
		}
	}

	return S;
}

/**
 * Returns the mean of each column in the provided matrix.
 * @param {number[][]} x - Two-dimensional matrix.
 */
function mean(x) {
	var result = [];
	
	for(var c = 0; c<x[0].length; c++){
		result.push(0);
	}
	
	for (var r = 0; r < x.length; r++) {
		for(var c = 0; c<x[r].length; c++){
			result[c] += x[r][c];
		}
	}
	
	for(var c = 0; c<x[0].length; c++){
		result[c] /= x.length;
	}
	
	return result;
}

exports.cov = cov;
exports.mean = mean;