What’s that “pre- and post-multiply” stuff?

January 5, 2013
By

(This article was first published on Industrial Code Workshop, and kindly contributed to R-bloggers)

Often in SEM scripts you will see matrices being pre- and post-multiplied by some other matrix. For instance, this figures in scripts computing the genetic correlation between variables. How does pre- and post-multiplying a variance/covariance matrix give us a correlation matrix? And what is it that we are multiplying this matrix by?

In general, a covariance matrix can be converted to a correlation matrix by pre- and post-multiplying by a diagonal matrix with 1/SD for each variable on the diagonal.
In R, matrix inversion (usually signified by A -1) is done using the solve() function.
For the diagonal case, the inverse of a matrix is simply 1/x in each cell.

Example with variance matrix A

`` A = matrix(nrow = 3, byrow = T,c(   1,0,0,   0,2,0,  0,0,3) );  solve(A)      [,1] [,2]  [,3] [1,]    1  0.0  0.00 [2,]    0  0.5  0.00 [3,]    0  0.0  0.33``
A number times its inverse = 1. For Matrices `solve(A) %*% A = Identity Matrix`
``solve(A) %*% A #  = I: The Standardized diagonal matrix     [,1] [,2] [,3][1,]    1    0    0[2,]    0    1    0[3,]    0    0    1``

An example with values (covariances) in the off-diagonals

``A = matrix(nrow = 3, byrow = T, c(    1, .5, .9,  .5,  2, .4, .9, .4,  4));I = matrix(nrow = 3, byrow = T, c(  1,  0, 0,  0,  1, 0, 0,  0, 1)); varianceA = I * A # zero the off-diagonal (regular, NOT matrix multiplication)sdMatrix  = sqrt(varianceA) # element sqrt to get SDs on diagonal: SD=sqrt(var)invSD     = solve(sdMatrix) # 1/SD = inverse of sdMatrixinvSD     [,1] [,2] [,3][1,]    1 0.00  0.0[2,]    0 0.71  0.0[3,]    0 0.00  0.5``
Any number times its inverse = 1, so this sweeps covariances into correlations
``corr = invSD %*% A %*% invSD # pre- and post- multiply by 1/SD     [,1] [,2] [,3][1,] 1.00 0.35 0.45[2,] 0.35 1.00 0.14[3,] 0.45 0.14 1.00``

Easy way of doing this in R

Using diag to grab the diagonal and make a new one, and capitalising on the fact that inv(X) = 1/x for a diagonal matrix
``diag(1/sqrt(diag(A))) %&% A # The %&% is a shortcut to pre- and post-mul     [,1] [,2] [,3][1,] 1.00 0.35 0.45[2,] 0.35 1.00 0.14[3,] 0.45 0.14 1.00``

Even-easier built-in way

``cov2cor(A)     [,1] [,2] [,3][1,] 1.00 0.35 0.45[2,] 0.35 1.00 0.14[3,] 0.45 0.14 1.00``Note: See also this followup post on getting a correlation matrix when you are starting with a lower-triangular Cholesky composition.``

R-bloggers.com offers daily e-mail updates about R news and tutorials on topics such as: Data science, Big Data, R jobs, visualization (ggplot2, Boxplots, maps, animation), programming (RStudio, Sweave, LaTeX, SQL, Eclipse, git, hadoop, Web Scraping) statistics (regression, PCA, time series, trading) and more...