scipy 在Python中生成相关数据(3.3)

bprjcwpo  于 2023-05-17  发布在  Python
关注(0)|答案(2)|浏览(106)

在R中有一个函数(cm.rnorm.cor,来自软件包CreditMetrics),它获取样本量、变量量和相关矩阵,以创建相关数据。
在Python中有等价的吗?

arknldoa

arknldoa1#

numpy.randomGenerator类的方法multivariate_normal就是您需要的函数。
示例:

import numpy as np
import matplotlib.pyplot as plt

num_samples = 400

# The desired mean values of the sample.
mu = np.array([5.0, 0.0, 10.0])

# The desired covariance matrix.
r = np.array([
        [  3.40, -2.75, -2.00],
        [ -2.75,  5.50,  1.50],
        [ -2.00,  1.50,  1.25]
    ])

# Generate the random samples.
rng = np.random.default_rng()
y = rng.multivariate_normal(mu, r, size=num_samples)

# Plot various projections of the samples.
plt.subplot(2,2,1)
plt.plot(y[:,0], y[:,1], 'b.', alpha=0.25)
plt.plot(mu[0], mu[1], 'ro', ms=3.5)
plt.ylabel('y[1]')
plt.axis('equal')
plt.grid(True)

plt.subplot(2,2,3)
plt.plot(y[:,0], y[:,2], 'b.', alpha=0.25)
plt.plot(mu[0], mu[2], 'ro', ms=3.5)
plt.xlabel('y[0]')
plt.ylabel('y[2]')
plt.axis('equal')
plt.grid(True)

plt.subplot(2,2,4)
plt.plot(y[:,1], y[:,2], 'b.', alpha=0.25)
plt.plot(mu[1], mu[2], 'ro', ms=3.5)
plt.xlabel('y[1]')
plt.axis('equal')
plt.grid(True)

plt.show()

结果:

参见SciPy Cookbook中的CorrelatedRandomSamples

wf82jlnq

wf82jlnq2#

如果你将协方差矩阵C Cholesky分解为L L^T,并生成一个独立的随机向量x,那么Lx将是一个协方差为C的随机向量。

import numpy as np
import matplotlib.pyplot as plt
linalg = np.linalg
np.random.seed(1)

num_samples = 1000
num_variables = 2
cov = [[0.3, 0.2], [0.2, 0.2]]

L = linalg.cholesky(cov)
# print(L.shape)
# (2, 2)
uncorrelated = np.random.standard_normal((num_variables, num_samples))
mean = [1, 1]
correlated = np.dot(L, uncorrelated) + np.array(mean).reshape(2, 1)
# print(correlated.shape)
# (2, 1000)
plt.scatter(correlated[0, :], correlated[1, :], c='green')
plt.show()

参考:参见Cholesky分解
如果要生成两个序列XY,并具有特定的(Pearson)相关系数(例如:0.2):

rho = cov(X,Y) / sqrt(var(X)*var(Y))

你可以选择协方差矩阵为

cov = [[1, 0.2],
       [0.2, 1]]

这使得cov(X,Y) = 0.2以及方差var(X)var(Y)都等于1。所以rho等于0.2。
例如,下面我们生成相关序列对XY,1000次。然后我们绘制相关系数的直方图:

import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats
linalg = np.linalg
np.random.seed(1)

num_samples = 1000
num_variables = 2
cov = [[1.0, 0.2], [0.2, 1.0]]

L = linalg.cholesky(cov)

rhos = []
for i in range(1000):
    uncorrelated = np.random.standard_normal((num_variables, num_samples))
    correlated = np.dot(L, uncorrelated)
    X, Y = correlated
    rho, pval = stats.pearsonr(X, Y)
    rhos.append(rho)

plt.hist(rhos)
plt.show()

正如您所看到的,相关系数通常接近0.2,但对于任何给定的样本,相关性很可能不是0.2。

相关问题