14

我想用 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)
4

8 回答 8

10

根据定义,正态分布从 -inf 延伸到 +inf,因此您所要求的在数学上没有意义。

您可以采用正态分布并将绝对值“剪辑”为正值,或者只是丢弃负值,但您应该了解它将不再是正态分布。

于 2013-05-01T02:44:48.580 回答
5

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

import numpy as np def PosNormal(mean, sigma): x = np.random.normal(xbar,delta_xbar,1) return(x if x>=0 else PosNormal(mean,sigma))

于 2016-07-16T00:16:39.623 回答
1

沿着这些路线使用对数正态怎么样:

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

    new_list = np.random.lognormal(mu, sigma, length_of_new_list)
于 2017-04-12T16:42:43.547 回答
1

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

于 2018-04-09T10:32:00.043 回答
1

或者,也许您可​​以通过减去最小值(或添加最小值的绝对值)将整个分布“转移”到“右侧”:

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])
于 2019-04-30T12:55:49.597 回答
0

您可以使用低比例的高位:

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]
于 2021-06-12T10:59:40.137 回答
0

这个问题是合理的。对于动机,考虑生物细胞的模拟。细胞中一种分子的计数分布可以近似为正态分布,但必须是非负的才能具有物理意义。

我的整个模拟器使用这种方法来采样分子计数的初始分布:

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上溢出堆栈的答案!)其次,我通过限制分布的样本数量来捕获可能错误的输入。

于 2020-12-11T19:20:34.420 回答
0

You can offset your entire array by the lowest value (left most) of the array. What you get may not be truly "normal distribution", but within the scope of your work, dealing with finite array, you can ensure that the values are positive and fits under a bell curve.

>>> 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])
于 2016-04-06T00:26:32.363 回答