【问题标题】:Setting a maximum number of replacements for sample with numpy choice使用 numpy 选择设置样本的最大替换次数
【发布时间】:2021-04-06 09:28:39
【问题描述】:

我想从具有最大替换次数的数组中选择一个随机样本。

举个例子:

import numpy as np
a = np.arange(3)

rng = np.random.default_rng(seed=3)
rng.choice(a, 5)

这会生成一个 [2, 0, 0, 0, 0] 数组。
在这里,元素0 被选中了四次。
有没有办法将其限制为例如两次?

【问题讨论】:

    标签: python numpy random


    【解决方案1】:

    没有内置方法可以做到这一点,但只要数字不太大,你可以使用

    rng.choice(a.repeat(2), 5, replace=False)
    

    来模拟。但是要注意,如果a或者重复次数很大,这是非常低效的。在这种情况下,编写自定义函数是有意义的。

    (查看documentation

    【讨论】:

      【解决方案2】:

      有几种方法可以使用您想要的限制。 您可以根据需要从中选择。

      如果你衡量你选择的方法的性能,你会得到:

      a = np.arange(3)                                                                                                                                                                          
      rng = np.random.default_rng(seed=3)                                                                                                                                                        
      timeit l=rng.choice(a, 5)                                                                                                                                                                  
      17.2 µs ± 334 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
      

      如果您想允许每个值最多使用两次,使用相同的方法不会使其更快:

      a = np.arange(3).repeat(2)                                                                                                                                                           
      rng = np.random.default_rng(seed=3)                                                                                                                                                   
      timeit l=rng.choice(a, 5)                                                                                                                                                                  
      17.3 µs ± 359 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
      

      但是,您可以使用自己的函数来实现更快的执行:

      import random
      
      def choice(a, n, l):
          choices=[]
          if len(a)*l<n:
              raise ValueError("Impossible")
          s={k:n for k in a}
          for _ in range(n):
              r=random.choice(list(s))
              choices.append(r)
              s[r]-=1
              if s[r]==0:
                  del(s[r])
          return choices
      
      random.seed(3)                                                                                                                                                                            
      timeit l=choice(range(3), 5, 2)                                                                                                                                                           
      3.71 µs ± 22.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
      

      如果你需要numpy array的结果,你可以转换它,浪费一点时间,但仍然足够快。

      【讨论】:

      • 对于小型 nl,您的非数组解决方案更快,但 numpy choice 可以更好地扩展。
      猜你喜欢
      • 2013-08-25
      • 1970-01-01
      • 1970-01-01
      • 2018-09-18
      • 1970-01-01
      • 2018-02-16
      • 2012-09-09
      • 2011-02-05
      • 1970-01-01
      相关资源
      最近更新 更多