33
$\begingroup$

UPDATE: Solution

Thanks to Greg Snow for pointing out the empirical = TRUE command in mvrnorm (multivariate random normal stuff)! Here's the explicit code:

samples = 200
r = 0.83

library('MASS')
data = mvrnorm(n=samples, mu=c(0, 0), Sigma=matrix(c(1, r, r, 1), nrow=2), empirical=TRUE)
X = data[, 1]  # standard normal (mu=0, sd=1)
Y = data[, 2]  # standard normal (mu=0, sd=1)

# Assess that it works
cor(X, Y)  # yay, r = 0.83!
cor(X*0.01 + 42, Y*3 - 1)  # Linear transformations of X and Y won't change r.

Original question

I want to generate two variables with (pseudo-) random numbers with an exact pearson's r. How do I do that? Python and/or R solutions would be nice!

I am able to generate random data that approximates a pre-specified r in python in the following way. I'm not searching for approximations but for data that with an exact pre-specified r, i.e. with r=0.83000 in the example below:

samples = 200
r = 0.83

# Generate pearson correlated data with approximately cor(X, Y) = r
import numpy as np
data = np.random.multivariate_normal([0, 0], [[1, r], [r, 1]], size=samples)
X, Y = data[:,0], data[:,1]

# That's it! Now let's take a look at the actual correlation:
import scipy.stats as stats
print 'r=', stats.pearsonr(X, Y)[0]

The motivation for knowing r is that I'm testing out (bayesian) statistical models that can infer r from data and they are a lot easier to evaluate when r is well specified.

$\endgroup$
0

1 Answer 1

20
$\begingroup$

For R you can use the mvrnorm function in the MASS package and set empirical=TRUE.

Or this post shows the steps in R for creating new variables with specific correlations to an existing variable.

$\endgroup$
3
  • 1
    $\begingroup$ The post for basing the new variable to one that already exists is precisely what I was looking for—is there somewhere that would explain why this code accomplishes what it accomplishes? I love that it works, but would love to know why it works. I'd be glad to make a new question about this, as well. $\endgroup$
    – Mark White
    Commented Nov 27, 2018 at 3:15
  • 1
    $\begingroup$ @MarkWhite, some of the explanation is in the post. A full explanation may be best in its own question, but here is a quick explanation. With one variable we could subtract the data mean and divide by the standard deviation to get a variable with mean 0 and sd 1, then multiply by the target sd and add the target mean. Here we do the same thing, but use the "square root" of the covariance/correlation matrix, first to make sure the covariance matrix is the identity, then to force the target correlations. $\endgroup$
    – Greg Snow
    Commented Nov 27, 2018 at 17:41
  • 1
    $\begingroup$ If this were anyone else I'd say this is more of a comment than an answer due to being mostly a link, but it's well received and by a top contributor who has helped me personally in the past I think so... I leave this for Mr. Snow to decide $\endgroup$
    – Hack-R
    Commented Jan 19, 2019 at 15:24

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