Mon, 08/01/2011 - 05:31

Hello all,

I am calculating the observed covariance matrix from the correlation matrix and the standard deviations. However, the resulting matrix apparently is not symmetric anymore (although judged by me it is...). Leading to the error message: The observed covariance matrix is not a symmetric matrix.

I hope somebody can help me out, thanks in advance!

Here is the code:

X = matrix(0,8,8)

val = c(1,.39,.35,.21,.32,.40,.39,.39,

1,.67,.11,.27,.29,.32,.29,1,.16,.29,

.28,.30,.37,1,.38,.30,.31,.42, 1,.47,

.42,.58,1,.41,.51,1,.42,1)

X[lower.tri(X, diag=TRUE)] = val

kaufcor = X + t(X) - diag(diag(X))

SD = matrix(0,8,8)

diag(SD) = c(3.40,2.40,2.90,2.70,2.70,4.20,2.80,3.00)

kaufcov = SD %*% kaufcor %*% SD

kaufcor==t(kaufcor)

kaufcov==t(kaufcov)

Looks like a matter of numerical precision.

You can fix this by choosing a finite precision (say, 10^-9), and rounding:

`roundCov <- round(kaufcov, 9)`

You'll find that this is perfectly symmetric.

What's happening is that you're reaching the boundaries of machine precision. Because R is using a finite-length binary representation of each number, there is often a little rounding at the last bit or two (like when a calculator abbreviates 2/3 as .667). As a result, small changes like the order in which operations occur can sometimes make differences appear in the last few bits.

If you do

`kaufcov - t(kaufcov)`

, you'll see these differences specifically. They're at the edges of machine precision, on the order of 10^-16. Rounding off the last few bits will make these differences disappear without losing much precision. You can also use`signif(kaufcov, #)`

if you know the number of significant digits you want to maintain.Great, thank you very much!