【发布时间】:2022-06-16 16:17:08
【问题描述】:
没有任何可用的原始/真实数据,我想生成一个类似于以下的玩具数据集:
| ID | gender | height_in_cm | weight_in_kg |
|---|---|---|---|
| 1 | M | 175 | 70 |
| 2 | M | 181 | 74 |
| 3 | F | 174 | 68 |
| 4 | F | 176 | 70 |
发行版应遵循一些要求:
- 男性/女性样本均等分布
- 身高和体重值保持在现实的范围内
此外,身高与性别相关,体重与身高相关。
受到 Robert Dodier 评论的启发,在 this blog post 和 this answer on Stack Overflow 的帮助下,我提出了以下 Python 实现:
import numpy as np
import pandas as pd
from scipy.linalg import cholesky
from sklearn.preprocessing import MinMaxScaler
df = pd.DataFrame(data=np.random.randint(2, size=10000), columns=["gender"])
# Generate 2 series of normally distributed (Gaussian) numbers
df[['height', 'weight']] = np.random.normal(0.0, 1.0, size=(10000, 2))
# Correlation matrix
correlation_matrix = np.array([[1.0, 0.0, 0.0],
[0.9, 1.0, 0.0],
[0.0, 0.9, 1.0]])
# Compute the (upper) Cholesky decomposition matrix
upper_cholesky = cholesky(correlation_matrix)
# Compute the inner product of upper_cholesky and the seed data frame
df.dot(upper_cholesky)
# restore the column names
df.columns =['gender', 'height_in_cm', 'weight_in_kg']
# scale values to desired ranges
height_scaler = MinMaxScaler(feature_range=(150, 200))
weight_scaler = MinMaxScaler(feature_range=(50, 120))
df[['height_in_cm']] = height_scaler.fit_transform(df[['height_in_cm']])
df[['weight_in_kg']] = weight_scaler.fit_transform(df[['weight_in_kg']])
# plot results
fig, ax = plt.subplots()
ax.scatter(df[df["gender"]==0][['height_in_cm']], df[df["gender"]==0][['weight_in_kg']], c="blue", label="Men")
ax.scatter(df[df["gender"]==1][['height_in_cm']], df[df["gender"]==1][['weight_in_kg']], c="red", label="Women")
plt.xlabel("Height")
plt.ylabel("Weight")
ax.legend()
我做错了什么,完成这项任务的最佳做法是什么?
【问题讨论】:
-
散点图显示身高和体重近似联合高斯分布。为了从具有协方差 S 的高斯生成随机样本,其中 S 是正定的,令 L 为下三角 Cholesky 分解,即 S = L 。 L' 其中引号表示换位。那么 y = L 。当 x 具有均值 0 且协方差 = 单位矩阵时,x 具有均值 0 和协方差 S(即 x 的元素是均值 0 和方差 1 的 iid 高斯分布)。现在只需为 y 添加一个平均值。您需要选择两个平均值,一个用于男性,一个用于女性。协方差也可能因性别而异。
标签: python statistics gaussian data-generation