在NumPy / Pandas中生成相关数

6
我正在尝试生成4个学科的模拟学生成绩,其中每个学生记录是一行数据。这里展示的代码将生成平均值为60,标准差为15的正态分布随机数。
df = pd.DataFrame(15 * np.random.randn(5, 4) + 60, columns=['Math', 'Science', 'History', 'Art'])

我无法理解的是如何使学生的科学成绩与数学成绩高度相关,而历史和艺术成绩则不太相关,但仍与数学成绩有一定关联。

我既不是统计学家也不是专业程序员,因此希望得到一个不太复杂但更易于理解的解决方案。


你有任何证明这些相关性的成绩数据吗?这将使生成有效的协方差矩阵更容易。你不需要在这里发布它(隐私),只需说明该数据的格式即可。 - Daniel F
无论如何,你所希望的是生成平均向量和协方差矩阵,并使用scipy.stats.multivariate_normal.rvs()函数以该分布生成随机数据。 - Daniel F
3个回答

6

让我们将@Daniel建议的内容转化为代码。

第一步

让我们导入multivariate_normal

import numpy as np
from scipy.stats import multivariate_normal as mvn

步骤2

让我们构建协方差数据并生成数据:

cov = np.array([[1, 0.8,.7, .6],[.8,1.,.5,.5],[0.7,.5,1.,.5],[0.6,.5,.5,1]])
cov

array([[ 1. ,  0.8,  0.7,  0.6],
       [ 0.8,  1. ,  0.5,  0.5],
       [ 0.7,  0.5,  1. ,  0.5],
       [ 0.6,  0.5,  0.5,  1. ]])

这是关键的一步。请注意,协方差矩阵对角线上的数为1,从左到右的协方差逐渐减小。

现在我们已经准备好生成数据了,让我们生成1,000个点:

scores = mvn.rvs(mean = [60.,60.,60.,60.], cov=cov, size = 1000)

健康检查(从协方差矩阵到简单相关性):

np.corrcoef(scores.T):

array([[ 1.        ,  0.78886583,  0.70198586,  0.56810058],
       [ 0.78886583,  1.        ,  0.49187904,  0.45994833],
       [ 0.70198586,  0.49187904,  1.        ,  0.4755558 ],
       [ 0.56810058,  0.45994833,  0.4755558 ,  1.        ]])

请注意,np.corrcoef希望您的数据按行排列。

最后,让我们将您的数据放入Pandas的DataFrame中:

df = pd.DataFrame(data = scores, columns = ["Math", "Science","History", "Art"])
df.head()

    Math        Science     History     Art
0   60.629673   61.238697   61.805788   61.848049
1   59.728172   60.095608   61.139197   61.610891
2   61.205913   60.812307   60.822623   59.497453
3   60.581532   62.163044   59.277956   60.992206
4   61.408262   59.894078   61.154003   61.730079

步骤三

让我们来可视化一些刚刚生成的数据:

ax = df.plot(x = "Math",y="Art", kind="scatter", color = "r", alpha = .5, label = "Art, $corr_{Math}$ = .6")
df.plot(x = "Math",y="Science", kind="scatter", ax = ax, color = "b", alpha = .2, label = "Science, $corr_{Math}$ = .8")
ax.set_ylabel("Art and Science");

enter image description here


1
统计工具是协方差矩阵:https://en.wikipedia.org/wiki/Covariance。每个单元格(i,j)表示变量i和变量j之间的依赖关系,所以在您的情况下,它可以在数学和科学之间。如果没有依赖性,则值为0。
您做的是假设协方差是对角矩阵,对角线上的值相同。因此,您需要定义协方差矩阵,然后从高斯分布中采样 numpy.random.multivariate_normal https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.multivariate_normal.html 或任何其他分布函数。

1
感谢大家的回复,它们非常有用。我采用Sergey提供的代码来得到我想要的结果,即数学和科学成绩相对较接近,历史和艺术成绩相对独立的记录。
以下数据看起来合理:
cov = np.array([[1, 0.5,.2, .1],[.5,1.,.1,.1],[0.2,.1,1,.3],[0.1,.1,.3,1]])
scores = mvn.rvs(mean = [0.,0.,0.,0.], cov=cov, size = 100)
df = pd.DataFrame(data = 15 * scores + 60, columns = ["Math","Science","History", "Art"])
df.head(10)

下一步是使每个主题具有不同的平均值,但我有一个想法可以做到这一点。再次感谢。 示例数据帧

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接