numpy.random.Generator.choice 提供了一个 replace 参数来采样,无需替换:
from numpy.random import default_rng
rng = default_rng()
numbers = rng.choice(20, size=10, replace=False)
如果您使用的是 1.17 之前的 NumPy,没有 Generator API,您可以使用标准库中的 random.sample():
print(random.sample(range(20), 10))
你也可以使用numpy.random.shuffle()和slicing,但是这样效率会降低:
a = numpy.arange(20)
numpy.random.shuffle(a)
print a[:10]
在旧的numpy.random.choice 函数中还有一个replace 参数,但是由于随机数流稳定性保证,此参数的实现效率低下,因此效率低下,因此不建议使用它。 (它基本上在内部进行洗牌和切片。)
一些时间安排:
import timeit
print("when output size/k is large, np.random.default_rng().choice() is far far quicker, even when including time taken to create np.random.default_rng()")
print(1, timeit.timeit("rng.choice(a=10**5, size=10**4, replace=False, shuffle=False)", setup="import numpy as np; rng=np.random.default_rng()", number=10**3)) #0.16003450006246567
print(2, timeit.timeit("np.random.default_rng().choice(a=10**5, size=10**4, replace=False, shuffle=False)", setup="import numpy as np", number=10**3)) #0.19915290002245456
print(3, timeit.timeit("random.sample( population=range(10**5), k=10**4)", setup="import random", number=10**3)) #5.115292700007558
print("when output size/k is very small, random.sample() is quicker")
print(4, timeit.timeit("rng.choice(a=10**5, size=10**1, replace=False, shuffle=False)", setup="import numpy as np; rng=np.random.default_rng()", number=10**3)) #0.01609779999125749
print(5, timeit.timeit("random.sample( population=range(10**5), k=10**1)", setup="import random", number=10**3)) #0.008387799956835806
所以numpy.random.Generator.choice 是您通常想要的,除了非常小的输出大小/k。