Here's the manual, or poor-man's, prove-it-to-myself demonstration:
> set.seed(0)
> # The correlation matrix
> corr_matrix = matrix(cbind(1, .80, .2, .80, 1, .7, .2, .7, 1), nrow=3)
> nvar = 3 # Three columns of correlated data points
> nobs = 1e6 # One million observations for each column
> std_norm = matrix(rnorm(nvar * nobs),nrow=nobs, ncol=nvar) # N(0,1)
$$\text{Corr}=\small \begin{bmatrix}
1 & .8 & .2\\
.8& 1 & .7 \\
.2&.7&1
\end{bmatrix}$$
$$\text{N}=\tiny \begin{bmatrix}
& [,1] & [,2] & [,3] \\
[1,] & -1.0806338 & 0.6563913 & 0.8400443 \\
[2,] & -1.1434241 & -0.1729738 & -0.9884772 \\
\vdots & \vdots & \vdots & \vdots \\
\vdots & \vdots & \vdots & \vdots \\
[999999,] & 0.4861827 & 0.03563006 & -2.1176976 \\
[1000000,] & -0.4394551 & 1.69265517 & -1.9534729\\
\end{bmatrix}$$
1. SVD METHOD:
$$\left[ \bf \underset{[3 \times 3]}{\color{blue}{\Large\,U}}\,\,\,\,\,\underset{\tiny \begin{bmatrix}\sqrt{d_1}&0&0\\0&\sqrt{d_2}&0\\0&0&\sqrt{d_3}\end{bmatrix}}{\Large\color{blue}{\Sigma^{0.5}}} \, \underset{[3\times 10^6]}{\Large\color{blue}{N^T}} \right]^T$$
> ptm <- proc.time()
> # Singular Value Decomposition method:
> svd = svd(corr_matrix)
> rand_data_svd = t(svd$u %*% (diag(3) * sqrt(svd$d)) %*% t(std_norm))
> proc.time() - ptm
user system elapsed
0.29 0.05 0.34
>
> ptm <- proc.time()
2. CHOLESKY METHOD:
$$\bf \left[ \underset{\begin{bmatrix}c_{11}&0&0\\c_{21}&c_{22}&0\\c_{31}&c_{32}&c_{33}\end{bmatrix}}{\Large\color{blue}{\text{Ch}}}\,\,\underset{[3\times 10^6]}{\Large\color{blue}{N^T}} \right]^T$$
> # Cholesky method:
> chole = t(chol(corr_matrix))
> rand_data_chole = t(chole %*% t(std_norm))
> proc.time() - ptm
user system elapsed
0.25 0.03 0.31
Thank you to @userr11852 for pointing out to me that there is a better way to calculate the difference in performance between SVD and Cholesky, in favor of the latter, using the function microbenchmark
. At his suggestion, here is the result:
microbenchmark(chol(corr_matrix), svd(corr_matrix))
Unit: microseconds
expr min lq mean median uq max neval cld
chol(corr_matrix) 24.104 25.05 28.74036 25.995 26.467 95.469 100 a
svd(corr_matrix) 108.701 110.12 116.27794 111.065 112.719 223.074 100 b
car::ellipse
). Although the question is asked in different application, the theory behind is the same. You will see nice figures for geometric explanation there. $\endgroup$