Python numpy.random.normal只允许正值

v64noz0r  于 2023-08-05  发布在  Python
关注(0)|答案(9)|浏览(89)

我想用numpy.random.normal创建一个仅由正值组成的正态分布数组。例如,下面说明它有时返回负值,有时返回正值。我如何修改它,使它只返回正值?

>>> import numpy
>>> numpy.random.normal(10,8,3)
array([ -4.98781629,  20.12995344,   4.7284051 ])
>>> numpy.random.normal(10,8,3)
array([ 17.71918829,  15.97617052,   1.2328115 ])
>>>

字符串
我想我可以像这样解决它:

myList = numpy.random.normal(10,8,3)

while item in myList <0:
       # run again until all items are positive values
       myList = numpy.random.normal(10,8,3)

ztigrdn8

ztigrdn81#

根据定义,正态分布从-inf扩展到+inf,因此您所要求的在数学上没有意义。
你可以取一个正态分布,然后取绝对值“裁剪”到正值,或者只是丢弃负值,但你应该明白,它将不再是正态分布。

xggvc2p6

xggvc2p62#

我假设你的意思是你想修改概率密度,使它在正范围内与正常情况下的形状相同,而在负范围内为零。这是一个非常常见的实际案例。在这种情况下,不能简单地取生成的正态随机变量的绝对值。相反,你必须生成一个新的独立的正态分布数,直到你得到一个正数。一种方法是递归,见下文。
第一个月

pprl5pva

pprl5pva3#

如何使用对数正态分布:

mu = np.mean(np.log(list))
    sigma = np.std(np.log(list))

    new_list = np.random.lognormal(mu, sigma, length_of_new_list)

字符串

cs7cruho

cs7cruho4#

data = np.random.randint(low=1,high=100,size=(4,4),dtype='int')

t30tvxxf

t30tvxxf5#

或者你可以通过减去min(或加上min的abs瓦尔)来将整个分布“向右移动”:

y = np.random.normal(0.0, 1.0, 10)

y
array([-0.16934484,  0.06163384, -0.29714508, -0.25917105, -0.0395456 ,
        0.17424635, -0.42289079,  0.71837785,  0.93113373,  1.12096384])

y - min(y)
array([0.25354595, 0.48452463, 0.12574571, 0.16371974, 0.38334519,
       0.59713714, 0.        , 1.14126864, 1.35402452, 1.54385463])

字符串

fykwrbwg

fykwrbwg6#

这个问题是合理的。对于动机,考虑simulations of biological cells。细胞中一种类型的分子的计数的分布可以通过正态分布来近似,但必须是非负的才有物理意义。
我的全模拟器使用这种方法来采样分子计数的初始分布:

def non_neg_normal_sample(random_state, mean, std, max_iters=1000):
    """ Obtain a non-negative sample from a normal distribution

    The distribution returned is normal for 0 <= x, and 0 for x < 0

    Args:
        random_state (:obj:`numpy.random.RandomState`): a random state
        mean (:obj:`float`): mean of the normal dist. to sample
        std (:obj:`float`): std of the normal dist. to sample
        max_iters (:obj:`int`, optional): maximum number of draws of the true normal distribution

    Returns:
        :obj:`float`: a normal sample that is not negative

    Raises:
        :obj:`ValueError`: if taking `max_iters` normal sample does not obtain one that is not negative
    """
    iter = 0
    while True:
        sample = random_state.normal(mean, std)
        iter += 1
        if 0 <= sample:
            return sample
        if max_iters <= iter:
            raise ValueError(f"{iter} draws of a normal dist. with mean {mean:.2E} and std {std:.2E} "
                             f"fails to obtain a non-negative sample")

字符串
我从两个方面来扩展@ gena-kukartsev的答案:首先,我避免了可能使调用堆栈溢出的递归。(让我们避免可能溢出stackoverflow堆栈的答案!第二,我通过限制分布的样本数量来捕捉可能的错误输入。

0s7z1bwu

0s7z1bwu7#

您可以将整个数组偏移数组的最小值(最左侧)。你得到的可能不是真正的“正态分布”,但是在你的工作范围内,处理有限数组,你可以确保值是正的,并且符合钟形曲线。

>>> mu,sigma = (0,1.0)
>>> s = np.random.normal(mu, 1.0, 100)
>>> s
array([-0.58017653,  0.50991809, -1.13431539, -2.34436721, -1.20175652,
        0.56225648,  0.66032708, -0.98493441,  2.72538462, -1.28928887])
>>> np.min(s)
-2.3443672118476226
>>> abs(np.min(s))
2.3443672118476226
>>> np.add(s,abs(np.min(s)))
array([ 1.76419069,  2.85428531,  1.21005182,  0.        ,  1.14261069,
        2.90662369,  3.00469429,  1.3594328 ,  5.06975183,  1.05507835])

字符串

laawzig2

laawzig28#

您可以使用高位置和低比例:

np.random.normal(100, 10, 10) /100

[0.96568643 0.92123722 0.83242272 0.82323367 1.07532713 0.90125736
 0.91226052 0.90631754 1.08473303 0.94115643]

字符串

hrysbysz

hrysbysz9#

arr=np.random.normal(0,1,10)
arr[gdp_cap<0]=-arr[gdp_cap<0] #Just invert the elements less than 0
print(gdp_cap)

字符串

相关问题