In general, if you want to draw a $N \times 1$ random vector $x$ with a multivariate normal distribution with mean zero and $N \times N$ variance matrix $\Sigma$, then you do the following:
- Draw $N$ independent and identically distributed $N(0,1)$ random variables, and stack them up in a vector $y$.
- Calculate the Cholesky decomposition of $\Sigma$ (the CC' form). I think all statistical programming languages have a function to do this.
R
has it in the function chol
.
- Multiply $x=Cy$
- Now, $x$ is distributed normal with mean zero and variance $\Sigma$.
The other part of your question is how to construct $\Sigma$. You did not say anything about the variances of the $\alpha,\beta$, so I am going to assume that each $\alpha$ needs to have variance $\sigma^2_\alpha$ and each $\beta$ needs to have variance $\sigma^2_\beta$.
First, let's be clear about how we are stacking up the $\alpha$s and $\beta$s to make our vector $x$:
\begin{align}
x = \left( \begin{array}{l}
\alpha_1 \\
\beta_1 \\
\alpha_2\\
\beta_2\\
\vdots \\
\alpha_N\\
\beta_N
\end{array}
\right)
\end{align}
Since you want the correlation between each $\alpha,\beta$ pair to be $\rho$, that means that the correlation matrix will start out (before we deal with the adjacency
correlations) looking like:
\begin{align}
\left[ \begin{array}{l l l l l l l l}
1 & \rho & 0 & 0 & 0 & \cdots & 0 & 0\\
\rho & 1 & 0 & 0 & 0 & \cdots & 0 & 0\\
0 & 0 & 1 & \rho & 0 & \cdots & 0 & 0\\
0 & 0 & \rho & 1 & 0 & \cdots & 0 & 0\\
\vdots &&&\vdots&&&& \vdots\\
0 & 0 & 0 & 0 & 0 & \cdots & 1 & \rho\\
0 & 0 & 0 & 0 & 0 & \cdots & \rho & 1\\
\end{array}
\right]
\end{align}
You don't say anything about how you want the adjacent nodes' variables to be correlated. So, I'll assume you want the correlation between two adjacent nodes' $\alpha$s to be $\rho_\alpha$, the correlation between two adjacent nodes' $\beta$s to be $\rho_\beta$ and the "cross-correlation" between the $\alpha$ and $\beta$ of two adjacent nodes to be $\rho_{\alpha\beta}$.
Let's imagine that nodes 1 and 2 are adjacent to one another and that nodes 1 and N are adjacent to one another. Then, we want the correlation matrix to look like:
\begin{align}
\left[ \begin{array}{l l l l l l l l}
1 & \rho & \rho_\alpha & \rho_{\alpha\beta} & 0 & \cdots & \rho_\alpha & \rho_{\alpha\beta}\\
\rho & 1 & \rho_{\alpha\beta} & \rho_\beta & 0 & \cdots & \rho_{\alpha\beta} & \rho_\beta\\
\rho_\alpha & \rho_{\alpha\beta} & 1 & \rho & 0 & \cdots & 0 & 0\\
\rho_{\alpha\beta} & \rho_\beta & \rho & 1 & 0 & \cdots & 0 & 0\\
0 & 0 & 0 & 0 & 1 & \cdots & 0 & 0\\
\vdots &&&\vdots&&&& \vdots\\
0 & 0 & 0 & 0 & 0 & \cdots & 0 & 0\\
\rho_\alpha & \rho_{\alpha\beta} & 0 & 0 & 0 & \cdots & 1 & \rho\\
\rho_{\alpha\beta} & \rho_\beta & 0 & 0 & 0 & \cdots & \rho & 1\\
\end{array}
\right]
\end{align}
To get this, we add, to the starting correlation matrix, the matrix:
\begin{align}
A \otimes \left[\begin{array}{l l}
\rho_\alpha & \rho_{\alpha\beta}\\
\rho_{\alpha\beta} & \rho_\beta
\end{array}
\right]
\end{align}
In that expression, $\otimes$ means kroenecker product, and $A$ is the adjacency matrix (I'm assuming symmetric).
That's almost it. One problem may arise. We have not done anything to assure that the correlation matrix we have constructed is positive definite. If there are a lot of adjacencies and if the correlations we have assigned have large absolute values, then there is a chance that the matrix will not be positive definite. You must check for this before calculating the Choleski decomposition, and if the matrix is not positive definite, you have to make the correlations smaller in absolute value.
So, the steps in doing the draw are:
- Choose the correlations, $\rho$, $\rho_\alpha$, $\rho_\beta$, $\rho_{\alpha\beta}$
- Choose the variances of $\alpha$ and $\beta$: $\sigma^2_\alpha$, $\sigma^2_\beta$
- If you don't want $\alpha$ and $\beta$ to have zero means, then choose their means: $\mu_\alpha,\mu_\beta$.
- Construct the "starting" correlation matrix above
- Add the kroenecker product matrix to the starting correlation matrix to get the final correlation matrix
- Check that the final correlation matrix is positive definite. If not, lower the correlations in step 1 and try again.
- Take the choleski decompostion of the final correlation matrix
- Draw $2N$ normal (0,1) random variables and stack them up in a vector $y$
- Multiply the vector $y$ by the choleski decomposition
- Multiply the $1^{\text{st}}$, $3^\text{rd}$, etc elements of $y$ by $\sqrt{\sigma^2_\alpha}$
- Multiply the $2^\text{nd}$, $4^\text{th}$, etc elements of $y$ by $\sqrt{\sigma^2}_\beta$
- Add $\mu_\alpha$ to the $1^{\text{st}}$, $3^\text{rd}$, etc elements of $y$
- Add $\mu_\beta$ to the $2^\text{nd}$, $4^\text{th}$, etc elements of $y$
I attach an R
program which does all this:
# This program written in response to a Cross Validated question
# http://stats.stackexchange.com/questions/123018/correlated-random-draws-with-graph-structured-correlation
# This program draws four pairs of random variables. Each is a pair with members named alpha, beta.
# Each pair of random variable is located at a node in a network. There is a 4 by 4 adjacency
# matrix, A, which shows which nodes are adjacent to one another. All random variables are
# normal
#
# Parameters:
#
# rho - correlation within nodes between alpha and beta
# rho_a - correlation between alphas of adjacent nodes
# rho_b - correlation between betas of adjacent nodes
# rho_ab - correlation between the alpha at one and the beta at the other adjacent nodes
#
# mu_a - mean of alpha
# mu_b - mean of beta
# sig_a - standard deviation of alpha
# sig_b - standard deviation of beta
#
# William B Vogt
library(matrixcalc)
set.seed(12344321)
# Set the parameters
rho <- 0.2
rho_a <- 0.3
rho_b <- 0.1
rho_ab <- 0.1
mu_a <- 0
mu_b <- 0
sig_a <- 2
sig_b <- 3
A <- matrix(c(0,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0),nrow=4,ncol=4)
print(A)
### Construct Sigma, the desired correlation matrix
# first, get the within-node correlations right
Sigma <- diag(4)%x%matrix(c(1,rho,rho,1),nrow=2,ncol=2)
# now, fill in the between-node correlations
Sigma <- Sigma + A%x%matrix(c(rho_a,rho_ab,rho_ab,rho_b),nrow=2,ncol=2)
# check that Sigma is positive definite
is.positive.definite(Sigma)
# factor it
C <- chol(Sigma) # This function works so that Sigma = C'C
# Draw and transform N(0,1) variates
# We need four nodes times 2 variables, or 8 variables:
x <- rnorm(8,mean=0,sd=1)
y <- t(C)%*%x
# Finally, extract alpha and beta and fix up their means and vars
alpha <- y[seq(from=1,to=7,by=2)]
beta <- y[seq(from=2,to=8,by=2)]
alpha <- alpha*sig_a + mu_a
beta <- beta*sig_b + mu_b
# Here is one draw on our network of four nodes:
cbind(alpha,beta)
# Just to check, let's do this draw 10000 times to make sure we are getting the correlations we want
x <- matrix(rnorm(80000,mean=0,sd=1),nrow=8,ncol=10000)
y <- t(C)%*%x
y <- t(y)
# If all is well, these two matrixes should be basically identical
cor(y)
Sigma