生成具有精确均值和标准差的样本数据。

11
我想创建一个具有特定均值和标准偏差的数据集。
使用 np.random.normal() 可以得到一个近似值。但是,为了进行我想要测试的内容,我需要一个精确的均值和标准偏差。
我已经尝试使用 norm.pdf 和 np.linspace 的组合,但生成的数据集也不匹配 (可能只是我的误用)。
重要的是数据集是否随机并不重要,只要我可以设置一个特定的样本大小、均值和标准偏差即可。
非常感谢您提供的帮助。
3个回答

14
最简单的方式是生成一些零均值的样本,使其标准差符合要求。然后从样本中减去平均值,以确保其均值为零。接着将样本进行缩放,使得标准差完全符合要求,最后再加上期望的均值。
以下是示例代码:
import numpy as np

num_samples = 1000
desired_mean = 50.0
desired_std_dev = 10.0

samples = np.random.normal(loc=0.0, scale=desired_std_dev, size=num_samples)

actual_mean = np.mean(samples)
actual_std = np.std(samples)
print("Initial samples stats   : mean = {:.4f} stdv = {:.4f}".format(actual_mean, actual_std))

zero_mean_samples = samples - (actual_mean)

zero_mean_mean = np.mean(zero_mean_samples)
zero_mean_std = np.std(zero_mean_samples)
print("True zero samples stats : mean = {:.4f} stdv = {:.4f}".format(zero_mean_mean, zero_mean_std))

scaled_samples = zero_mean_samples * (desired_std_dev/zero_mean_std)
scaled_mean = np.mean(scaled_samples)
scaled_std = np.std(scaled_samples)
print("Scaled samples stats    : mean = {:.4f} stdv = {:.4f}".format(scaled_mean, scaled_std))

final_samples = scaled_samples + desired_mean
final_mean = np.mean(final_samples)
final_std = np.std(final_samples)
print("Final samples stats     : mean = {:.4f} stdv = {:.4f}".format(final_mean, final_std))

生成类似于此输出的结果:

Initial samples stats   : mean = 0.2946 stdv = 10.1609
True zero samples stats : mean = 0.0000 stdv = 10.1609
Scaled samples stats    : mean = 0.0000 stdv = 10.0000
Final samples stats     : mean = 50.0000 stdv = 10.0000

原始样本数据的平均值为-0.005542,标准差为0.06089,但原始数据点的范围在-0.1208至0.14069之间。但是,在生成具有所需平均值(-0.005542)和标准差(0.06089)的新数据后,新生成的数据点的范围在(-26.847, 27.9262)之间。是否有办法限制新数据点偏离原始数据范围的最大标准差不超过1个? - user3762120
原始样本数据的平均值为-0.005542,标准差为0.06089,但原始数据点的范围在-0.1208到0.14069之间。但是,在生成具有所需平均值(-0.005542)和标准差(0.06089)的新数据后,新生成的数据点的范围在(-26.847, 27.9262)之间。是否有办法限制新数据点偏离原始数据范围的最大标准差不超过1个? - user3762120
有没有办法限制 final_samples 的最大值和最小值? - Louie Lee

6

对于后来查看此信息的其他人,Python 3.8+ 版本提供了 statistics.NormalDist 类专门用于此目的:

import statistics as s
n = s.NormalDist(mu=10, sigma=2)
samples = n.samples(100_000, seed=42)  # remove seed if desired
print(s.mean(samples))  # 10.004521585462394
print(s.stdev(samples))  # 2.0052615406360457

@Spoonless 的回答中提供的方法可以用来调整所需样本的精确均值和标准差,或者可以仅使用足够多的样本来获得极度接近的结果 - 毕竟这是统计学。


0

你也可以使用random库来完成这个操作。

import random as rand
mean = 20.9
stdd = 3
samples = 1000
data = [rand.normalvariate(mean, stdd) for i in range(samples)]

我也需要生成带有残差的数据,所以我只需将rand.randomrange(-1,1)的乘积与残差相加即可。

data = [rand.normalvariate(mean, stdd)+(rand.randrange(-1,1)*residual) for i in range(samples)]

通过添加残差,您将略微改变准确的平均值和标准偏差。

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