I would like to generate test data for script used for correlation analysis between quite long variables.
Is it possible for a given length of vectors, to generate in relatively simple way deterministic input data that have Pearson correlation coefficient equal almost exactly given r (e.g. 0.5,0.6.,0.7, etc.) ?

In R I tried something like the following:

#0.7 ---> r = 0.691


 #0.4 ---> r = 0.39918


 #0 ---> r = 6.526891e-06 


I'm looking for a (relatively) compact formula that generates such input vectors of length $n$ for given $r$ with required precision (e.g.precision=0.000001)

To simplify problem I don't care about p-value/significance.


If what needs to be deterministic is the correlation coefficient, you may use the option empirical=T option in mvrnorm, as in

correlation.coeff <- 0.6
correlation.matrix <- matrix(c(1,correlation.coeff,correlation.coeff,1),ncol=2)
mu <- runif(2) # could be anything
x <- mvrnorm(n = 1000, empirical = TRUE, mu = mu, Sigma = correlation.matrix)

Empirical correlation is as specified:

> cor(x[,1],x[,2])
[1] 0.6

If you want the data to be reproducible, you can use set.seed(1).

Why? I stripped the code of mvrnorm of some error and robustness checks. Note mvrnorm.simple is not safe to use in general.

mvrnorm.simple <- function (n, mu, Sigma, empirical = FALSE) {
  p <- length(mu)
  eS <- eigen(Sigma, symmetric = TRUE)
  ev <- eS$values
  X <- matrix(rnorm(p * n), n)
  if (empirical) {
    X <- scale(X, TRUE, FALSE)
    X <- X %*% svd(X)$v
    X <- scale(X, FALSE, TRUE)
  X <- mu + eS$vectors %*% diag(sqrt(ev), p) %*%t(X)

So what empirical=T does is to columnwise demean the $n\times p$ matrix of standard normals to get $\tilde X$, multiply with the matrix $V$ of the singular value decomposition $\tilde X=UDV'$ to then scale each columns by its root mean square, see also ?scale.

This ensures that the random draws to which the penultimate line of the code is applied have exact (up to numerical inaccuracies) sample means and covariances of zero and variances of one.

| cite | improve this answer | |
  • $\begingroup$ It would be nice to know how this option actually works, which as presented is just an uninformative black box solution. Could you provide an explanation? $\endgroup$ – whuber Mar 14 '19 at 18:36
  • $\begingroup$ @whuber, I tried to do so, but my intuition regarding the SVD is limited. $\endgroup$ – Christoph Hanck Mar 15 '19 at 9:28

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.