【发布时间】: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 被选中了四次。
有没有办法将其限制为例如两次?
【问题讨论】:
我想从具有最大替换次数的数组中选择一个随机样本。
举个例子:
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 被选中了四次。
有没有办法将其限制为例如两次?
【问题讨论】:
没有内置方法可以做到这一点,但只要数字不太大,你可以使用
rng.choice(a.repeat(2), 5, replace=False)
来模拟。但是要注意,如果a或者重复次数很大,这是非常低效的。在这种情况下,编写自定义函数是有意义的。
(查看documentation)
【讨论】:
有几种方法可以使用您想要的限制。 您可以根据需要从中选择。
如果你衡量你选择的方法的性能,你会得到:
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的结果,你可以转换它,浪费一点时间,但仍然足够快。
【讨论】:
n 和 l,您的非数组解决方案更快,但 numpy choice 可以更好地扩展。