7
$\begingroup$

I am trying to generate a simulated data matrix that is correlated by both observation and variable directions. So far I know how to do this for variable x variable.

enter image description here

 # correlated matrix between variables 
    n = 200
    p = 100 
    CRMt <- matrix(NA, nrow = p, ncol = p)
    diag(CRMt) <- 1
    CRMt[upper.tri (CRMt, diag = FALSE)] <- 0.5
    CRMt[lower.tri (CRMt, diag = FALSE)] <- 0.5

L = chol(CRMt)# Cholesky decomposition
p = dim(L)[1]

set.seed(999)
M = t(L) %*% matrix(rnorm(p*n), nrow=p, ncol=n)
M1 <- t(M)
rownames(M1) <- paste("S", 1:200, sep = "") 
colnames(M1) <- paste("M", 1:100, sep = "")
cor(M1)

Now say I want to create a data matrix that also follows the following observation x observation correlation matrix.

enter image description here

OCRMt <- matrix(NA, nrow = n, ncol = n)
diag(OCRMt) <- 1
OCRMt[upper.tri (OCRMt, diag = FALSE)] <- 0.3
OCRMt[lower.tri (OCRMt, diag = FALSE)] <- 0.3

How can I do this ?

$\endgroup$
7
+50
$\begingroup$

You can do the same thing that you did to the columns of the matrix to make them correlated, just do it to the rows instead. This will adjust the correlation on the observations within a column without affecting the correlations between the columns much:

L = chol(OCRMt)# Cholesky decomposition
p = dim(L)[1]

M2 <- t(L) %*% M1

hist( cor(M2)[ lower.tri(cor(M2), diag=FALSE)])
hist( cor(t(M2))[ lower.tri(cor(t(M2)), diag=FALSE)])

You can also create one observation from a distribution with n times p columns, then wrap that into your matrix. The correlation matrix is the Kronecker product of your other correlation matrices. My computer ran out of memory for your example, but works for a smaller matrix:

library(MASS)
vcmat <- matrix( 0.5, 10,10 )
diag(vcmat) <- 1

ocmat <- matrix( 0.3, 20,20 )
diag(ocmat) <- 1

cmat <- kronecker( ocmat, vcmat )

obs <- matrix( mvrnorm(1, mu=rep(0,10*20), Sigma=cmat), 20, 10 )

hist(cor(obs))
hist(cor(t(obs))) 
$\endgroup$
  • 1
    $\begingroup$ Greg, can you give, please, a numeric example in line with your code? For people not using R to be able to repeat your idea outside of R? $\endgroup$ – ttnphns Jun 5 '14 at 6:44
  • $\begingroup$ @ttnphns, For the 1st example I just multiply the Cholesky decomposition of the correlation matrix by the matrix of the data and that creates the correlation among the rows. In the second case I computed the Kronecker product of the 2 correlation matrices and used that as the correlation structure for a single observation (could have multiplied it by a single column of iid normals), then wrapped the resulting vector into a matrix of the desired dimension. $\endgroup$ – Greg Snow Jun 5 '14 at 17:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.