Re: [R] R code for var-cov matrix given variances and correlations
Haynes, Maurice (NIH/NICHD) [EMAIL PROTECTED] writes: If the vector of variances were var.vec - c(14, 12, 7) and the vector of correlations were cor.vec - c(.4, .2, .5), then the vector of covariances would be: covAB(c(.4, .2, .5),c(14, 14, 12), c(12, 7, 7)) [1] 5.184593 1.979899 4.582576 and the variance-covariance matrix with covariances rounded to the first decimal place would be: vmat - matrix(c(14, 5.2, 2.0, 5.2, 12, 4.6, 2.0, 4.6, 7), + nrow=3) vmat [,1] [,2] [,3] [1,] 14.0 5.2 2.0 [2,] 5.2 12.0 4.6 [3,] 2.0 4.6 7.0 # First fill in the correlation matrix: V - matrix(NA,3,3) diag(V) - 1 V[lower.tri(V)] - c(.4, .2, .5) V[upper.tri(V)] - t(V)[upper.tri(V)] # then scale rows and columns D - diag(sqrt( c(14, 12, 7))) D %*% V %*% D # or, more efficiently s - sqrt( c(14, 12, 7)) sweep(sweep(V,1,s,*),2,s,*) -- O__ Peter Dalgaard Blegdamsvej 3 c/ /'_ --- Dept. of Biostatistics 2200 Cph. N (*) \(*) -- University of Copenhagen Denmark Ph: (+45) 35327918 ~~ - ([EMAIL PROTECTED]) FAX: (+45) 35327907 __ [EMAIL PROTECTED] mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
Re: [R] R code for var-cov matrix given variances and correlations
On 21 Dec, 2004, at 13:09, Haynes, Maurice (NIH/NICHD) wrote: Dear list members, Where can I find code for computing the p*p variance-covariance matrix given a vector of p variances (ordered varA, varB, ..., varp) and a vector of all possible correlations (ordered corAB, corAC, ..., corp-1,p)? Something like this (not tested): sd.vec - sqrt(var.vec) n - length(sd.vec) cor.mat - matrix(1, n, n) for (i in 2:n){ for (j in 1:i-1){ cor.mat[i,j] - cor.vec[(i-1)*(i-2)/2 + j] cor.mat[j,i] - cor.mat[i,j]}} cov.mat - cor.mat * outer(sd.vec, sd.vec) I hope that helps. David I know that the covariance between 2 variables is equal to the product of their correlation and their standard deviations: corAB * varA^.5 * varB^.5 and so: covAB - function(corAB, varA, varB) { corAB * varA^.5 * varB^.5 } If the vector of variances were var.vec - c(14, 12, 7) and the vector of correlations were cor.vec - c(.4, .2, .5), then the vector of covariances would be: covAB(c(.4, .2, .5),c(14, 14, 12), c(12, 7, 7)) [1] 5.184593 1.979899 4.582576 and the variance-covariance matrix with covariances rounded to the first decimal place would be: vmat - matrix(c(14, 5.2, 2.0, 5.2, 12, 4.6, 2.0, 4.6, 7), + nrow=3) vmat [,1] [,2] [,3] [1,] 14.0 5.2 2.0 [2,] 5.2 12.0 4.6 [3,] 2.0 4.6 7.0 So the question is: How can I generate a p*p variance-covariance matrix from a vector of variances and a vector of correlations without resorting to a construction like: vmat - matrix(rep(0, p*p), nrow=p) if (p == 2) { vmat[1,1] - var[1] vmat[1,2] - cor[1] * (var[1]^.5 * var[2]^.5) vmat[2,1] - cor[1] * (var[2]^.5 * var[1]^.5) vmat[2,2] - var[2] } if (p == 3) { vmat[1,1] - var[1] vmat[1,2] - cor[1] * (var[1]^.5 * var[2]^.5) vmat[1,3] - cor[2] * (var[1]^.5 * var[3]^.5) vmat[2,1] - cor[1] * (var[2]^.5 * var[1]^.5) vmat[2,2] - var[2] vmat[2,3] - cor[3] * (var[2]^.5 * var[3]^.5) vmat[3,1] - cor[2] * (var[3]^.5 * var[1]^.5) vmat[3,2] - cor[3] * (var[3]^.5 * var[2]^.5) vmat[3,3] - var[3] } and so forth? Thanks, Maurice Haynes National Institute of Child Health and Human Development Child and Family Research Section 6705 Rockledge Drive, Suite 8030 Bethesda, MD 20892 Voice: 301-496-8180 Fax: 301-496-2766 E-mail: [EMAIL PROTECTED] __ [EMAIL PROTECTED] mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html __ [EMAIL PROTECTED] mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
Re: [R] R code for var-cov matrix given variances and correlations
PD == Peter Dalgaard [EMAIL PROTECTED] on 21 Dec 2004 14:34:59 +0100 writes: PD Haynes, Maurice (NIH/NICHD) [EMAIL PROTECTED] writes: If the vector of variances were var.vec - c(14, 12, 7) and the vector of correlations were cor.vec - c(.4, .2, .5), then the vector of covariances would be: covAB(c(.4, .2, .5),c(14, 14, 12), c(12, 7, 7)) [1] 5.184593 1.979899 4.582576 and the variance-covariance matrix with covariances rounded to the first decimal place would be: vmat - matrix(c(14, 5.2, 2.0, 5.2, 12, 4.6, 2.0, 4.6, 7), + nrow=3) vmat [,1] [,2] [,3] [1,] 14.0 5.2 2.0 [2,] 5.2 12.0 4.6 [3,] 2.0 4.6 7.0 PD # First fill in the correlation matrix: PD V - matrix(NA,3,3) PD diag(V) - 1 PD V[lower.tri(V)] - c(.4, .2, .5) PD V[upper.tri(V)] - t(V)[upper.tri(V)] PD # then scale rows and columns PD D - diag(sqrt( c(14, 12, 7))) PD D %*% V %*% D PD # or, more efficiently PD s - sqrt( c(14, 12, 7)) PD sweep(sweep(V,1,s,*),2,s,*) and others give similar answers, not as nice as the sweep one. While I leave the exact comparisons and even more slick alternatives to Gabor (:-), yet another alternative is to look at cov2cor() which does Cov |-- Cor, i.e., the inverse of what the original poster wanted. The source of that function, e.g. in https://svn.r-project.org/R/trunk/src/library/stats/R/cor.R is cov2cor - function(V) { ## Purpose: Covariance matrix |-- Correlation matrix -- efficiently ## -- ## Arguments: V: a covariance matrix (i.e. symmetric and positive definite) ## -- ## Author: Martin Maechler, Date: 12 Jun 2003, 11:50 p - (d - dim(V))[1] if(!is.numeric(V) || length(d) != 2 || p != d[2]) stop(`V' is not a square numeric matrix) Is - sqrt(1/diag(V)) # diag( 1/sigma_i ) if(any(!is.finite(Is))) warning(diagonal has non-finite entries) r - V # keep dimnames r[] - Is * V * rep(Is, each = p) ## == D %*% V %*% D where D = diag(Is) r[cbind(1:p,1:p)] - 1 # exact in diagonal r } [ Note that this is the *real source* including comments, contrary to what you get when you just type 'cov2cor' in R ] What I've wanted to expose here are the lines Is - sqrt(1/diag(V)) # diag( 1/sigma_i ) .. r - V # keep dimnames r[] - Is * V * rep(Is, each = p) which shows ``how to'' compute Diag %*% Matrix %*% Diag, efficiently, probably a bit more even than Peter's nice double use of sweep(.., *) {and still keeping dimnames}. Martin __ [EMAIL PROTECTED] mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html