Marishka Usacheva Marishka Usacheva - 1 month ago 30
R Question

Conversion between covariance matrix and correlation matrix

I have a correlation matrix

cor.mat <- structure(c(1, -0.25, 0.11, 0.25, 0.18, -0.25, 1, -0.14, -0.22,
-0.15, 0.11, -0.14, 1, 0.21, 0.19, 0.25, -0.22, 0.21, 1, 0.53,
0.18, -0.15, 0.19, 0.53, 1), .Dim = c(5L, 5L))


I also have a matrix of standard errors

sd <- structure(c(0.33, 0.62, 1, 0.54, 0.47), .Dim = c(1L, 5L))

dim(cor.mat)
#[1] 5 5
dim(sd)
#[1] 1 5
is.matrix(cor.mat)
#[1] TRUE
is.matrix(sd)
#[1] TRUE

cov.mat <-cor2cov(cor.mat, sd)
# Error in sds * R : non-conformable arrays


So, the matrices have compatible dimensions, why doesn't
cor2cov
function work for me?

Answer

OK, I don't know where your cor2cov comes from. But actually, it is really straightforward to obtain covariance matrix from correlation matrix and standard errors:

cov.mat <- sweep(sweep(cor.mat, 1L, sd, "*"), 2L, sd, "*")

#          [,1]      [,2]    [,3]      [,4]      [,5]
#[1,]  0.108900 -0.051150  0.0363  0.044550  0.027918
#[2,] -0.051150  0.384400 -0.0868 -0.073656 -0.043710
#[3,]  0.036300 -0.086800  1.0000  0.113400  0.089300
#[4,]  0.044550 -0.073656  0.1134  0.291600  0.134514
#[5,]  0.027918 -0.043710  0.0893  0.134514  0.220900

Yes, it is just a symmetric row & column rescaling.

We can verify this by transforming this covariance matrix back to correlation matrix using cov2cor, which is exactly your correlation matrix:

all.equal(cov2cor(cov.mat), cor.mat)
# [1] TRUE

My guess on your cor2cov

If you read How to rescale a matrix by row / column, you will see there are lots of different ways for rescaling. The sweep used above is just one option.

R base function cov2cor(V) is using:

Is <- sqrt(1/diag(V))    ## inverse of square root diagonal (inverse of sd)
Is * V * rep(Is, each = p)

I think your cor2cov(R, sds) is written in the same style:

sds * R * rep(sds, each = p)    ## `sd` must be a vector

If so, sd must be a vector, otherwise "*" will complain (note, the error message you got is indeed reported from "*").


Your argument "the matrices have compatible dimensions" is a bogus one. Purely in terms of linear algebra, you need sd to be a diagonal matrix, so that you can do:

sd %*% cor.mat %*% sd

But row / column rescaling is never done by matrix computations as this is too expensive.