MWH*_*MWH 8 python random numpy normal-distribution
我想生成n个随机数,例如,n=200
其中可能值的范围在2到40之间,平均值为12,中值为6.5.
我到处搜索,我找不到解决方案.我尝试了下面的脚本,它适用于20等小数字,对于大数字,它需要很长时间并返回结果.
n=200
x = np.random.randint(0,1,size=n) # initalisation only
while True:
if x.mean() == 12 and np.median(x) == 6.5:
break
else:
x=np.random.randint(2,40,size=n)
Run Code Online (Sandbox Code Playgroud)
任何人都可以通过改进这个来帮助我获得快速结果,即使n = 5000左右?
一种获得与实际所需结果非常接近的结果的方法是,生成两个单独的长度为100的随机范围,该范围满足您的中值约束,并包括所有期望的数字范围。然后,通过连接数组,均值将在12左右,但不完全等于12。但是由于这只是意味着您正在处理,可以通过调整这些数组之一来简单地生成预期结果。
In [162]: arr1 = np.random.randint(2, 7, 100)
In [163]: arr2 = np.random.randint(7, 40, 100)
In [164]: np.mean(np.concatenate((arr1, arr2)))
Out[164]: 12.22
In [166]: np.median(np.concatenate((arr1, arr2)))
Out[166]: 6.5
Run Code Online (Sandbox Code Playgroud)
以下是通过限制随机序列的创建,针对任何其他用于循环或python级代码的解决方案的矢量化和经过优化的解决方案:
import numpy as np
import math
def gen_random():
arr1 = np.random.randint(2, 7, 99)
arr2 = np.random.randint(7, 40, 99)
mid = [6, 7]
i = ((np.sum(arr1 + arr2) + 13) - (12 * 200)) / 40
decm, intg = math.modf(i)
args = np.argsort(arr2)
arr2[args[-41:-1]] -= int(intg)
arr2[args[-1]] -= int(np.round(decm * 40))
return np.concatenate((arr1, mid, arr2))
Run Code Online (Sandbox Code Playgroud)
演示:
arr = gen_random()
print(np.median(arr))
print(arr.mean())
6.5
12.0
Run Code Online (Sandbox Code Playgroud)
函数背后的逻辑:
为了使我们具有符合该条件的随机数组,我们可以将3个数组连接在一起arr1
,mid
并且arr2
。arr1
并arr2
分别容纳99个项目和mid
2个项目6和7,因此最终结果的中位数为6.5。现在我们创建两个随机数组,每个数组的长度为99。要使结果具有12个均值,我们要做的就是找到当前总和之间的差,12 * 200
并从我们的N个最大数中减去结果,在这种情况下,可以从中选择arr2
和使用N=50
。
编辑:
如果结果中包含浮点数不是问题,那么您实际上可以按以下方式缩短函数:
import numpy as np
import math
def gen_random():
arr1 = np.random.randint(2, 7, 99).astype(np.float)
arr2 = np.random.randint(7, 40, 99).astype(np.float)
mid = [6, 7]
i = ((np.sum(arr1 + arr2) + 13) - (12 * 200)) / 40
args = np.argsort(arr2)
arr2[args[-40:]] -= i
return np.concatenate((arr1, mid, arr2))
Run Code Online (Sandbox Code Playgroud)