如何生成随机数以满足python中的特定均值和中位数?

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左右?

Kas*_*mvd 5

一种获得与实际所需结果非常接近的结果的方法是,生成两个单独的长度为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个数组连接在一起arr1mid并且arr2arr1arr2分别容纳99个项目和mid2个项目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)