【问题标题】:Binary random array with a specific proportion of ones?具有特定比例的二进制随机数组?
【发布时间】:2013-11-05 00:32:00
【问题描述】:

生成随机数的零和具有特定比例的零的有效方法(可能使用 Matlab 术语进行矢量化)是什么?特别是 Numpy?

由于我的情况是 1/3 的特殊情况,我的代码是:

import numpy as np 
a=np.mod(np.multiply(np.random.randomintegers(0,2,size)),3)

但是至少对于 K 和 N 是自然数的K/N 的情况,是否有任何内置函数可以更有效地处理这个问题?

【问题讨论】:

  • 您需要比例完全为给定值,还是只是样本的预期比例?
  • 另外,当size 不能被 3 整除时,1/3 的情况会发生什么?例外?圆形/地板/截断?加权随机回合(所以 10 有 3 的 2/3 机会和 4 的 1/3 机会)?
  • @WarrenWeckesser,这是我的预期比例。我希望你没有删除你的答案,所以我会接受它。
  • @Naji:我恢复了我的答案。如果你需要精确的比例,那这个方法就行不通了。
  • @Naji:你想要什么?我希望它产生一万亿美元,而它给我的只是一个数组。我想我还不够相信。 ;)

标签: python arrays random numpy random-sample


【解决方案1】:

简单的单线:您可以避免使用整数列表和概率分布,在我看来,这对于这个问题来说是不直观且过度杀伤力的,只需先使用bools,然后在必要时转换为int(尽管在大多数情况下将其保留为 bool 数组应该可以工作)。

>>> import numpy as np
>>> np.random.random(9) < 1/3.
array([False,  True,  True,  True,  True, False, False, False, False])   
>>> (np.random.random(9) < 1/3.).astype(int)
array([0, 0, 0, 0, 0, 1, 0, 0, 1])    

【讨论】:

  • 这并不能保证像 mdml 的答案那样的正确比例。
  • OP 说他们希望 1/3 是 1 的预期比例,而不是确切的比例。
【解决方案2】:

另一种获取确切数量的 1 和 0 的方法是使用 np.random.choice 对索引进行抽样而不进行替换:

arr_len = 30
num_ones = 8

arr = np.zeros(arr_len, dtype=int)
idx = np.random.choice(range(arr_len), num_ones, replace=False)
arr[idx] = 1

输出:

arr

array([0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1,
       0, 0, 0, 0, 0, 1, 0, 0])

【讨论】:

    【解决方案3】:

    另一种方法,使用np.random.choice

    >>> np.random.choice([0, 1], size=(10,), p=[1./3, 2./3])
    array([0, 1, 1, 1, 1, 0, 0, 0, 0, 0])
    

    【讨论】:

    • 请注意,这种方法不会为您提供您所要求的零和一的确切比例。 . .下面@mdml 的答案将。
    • 是的,既然它被接受了,我认为 Cupitor 可能在他的程序中添加了一个错误
    • @JFFIGK,dbliss:这在问题的 cmets 中进行了讨论。那些 cmets 还在那里,所以看看吧。
    【解决方案4】:

    如果我正确理解您的问题,您可能会通过numpy.random.shuffle 获得一些帮助

    >>> def rand_bin_array(K, N):
        arr = np.zeros(N)
        arr[:K]  = 1
        np.random.shuffle(arr)
        return arr
    
    >>> rand_bin_array(5,15)
    array([ 0.,  1.,  0.,  1.,  1.,  1.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,
            0.,  0.])
    

    【讨论】:

      【解决方案5】:

      一个简单的方法是首先生成一个ndarray,其中包含您想要的零和一的比例:

      >>> import numpy as np
      >>> N = 100
      >>> K = 30 # K zeros, N-K ones
      >>> arr = np.array([0] * K + [1] * (N-K))
      >>> arr
      array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
             1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
             1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
             1, 1, 1, 1, 1, 1, 1, 1])
      

      那么你就可以shuffle这个数组,让分布随机化:

      >>> np.random.shuffle(arr)
      >>> arr
      array([1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0,
             1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1,
             1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
             0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1,
             1, 1, 1, 0, 1, 1, 1, 1])
      

      请注意,与二项式方法不同,此方法将为您提供您请求的 精确比例的 0/1。如果您不需要确切的比例,那么二项式方法就可以了。

      【讨论】:

      • 我多么愚蠢!是的,我忘记了二进制分发。实际上有人在您之前发布了二进制文件,但他删除了他的答案(不知道为什么!!)
      • 这很聪明
      【解决方案6】:

      您可以使用numpy.random.binomial。例如。假设frac是个的比例:

      In [50]: frac = 0.15
      
      In [51]: sample = np.random.binomial(1, frac, size=10000)
      
      In [52]: sample.sum()
      Out[52]: 1567
      

      【讨论】:

      • 这并不能保证像 mdml 的答案那样的正确比例。
      • @John,这已在问题的 cmets 中进行了讨论。看看吧。
      • 我现在明白了!当然问题需要编辑,因为它要求特定的比例。
      猜你喜欢
      • 2015-09-04
      • 2011-01-05
      • 2019-09-13
      • 2014-03-01
      • 1970-01-01
      • 2015-07-30
      • 1970-01-01
      • 2016-08-31
      相关资源
      最近更新 更多