115

如何在 numpy 中生成非重复随机数?

list = np.random.random_integers(20,size=(10))
4

6 回答 6

143

numpy.random.Generator.choice提供了一个replace无需替换的 sample 的论点:

from numpy.random import default_rng

rng = default_rng()
numbers = rng.choice(20, size=10, replace=False)

如果您使用的是 1.17 之前的 NumPy,没有GeneratorAPI,您可以random.sample()从标准库中使用:

print(random.sample(range(20), 10))

您也可以使用numpy.random.shuffle()和切片,但这会降低效率:

a = numpy.arange(20)
numpy.random.shuffle(a)
print a[:10]

replace在 legacy函数中还有一个参数numpy.random.choice,但是这个参数实现效率低,然后由于随机数流稳定性保证而效率低下,因此不推荐使用它。(它基本上在内部进行洗牌和切片。)

一些时间安排:

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

于 2011-12-14T14:03:02.730 回答
127

我觉得numpy.random.sample现在不行 这是我的方式:

import numpy as np
np.random.choice(range(20), 10, replace=False)
于 2014-08-07T05:24:56.560 回答
6

多年后,从 10000^2(Numpy 1.8.1,imac 2.7 GHz)中选择 40000 的一些时间:

import random
import numpy as np

n = 10000
k = 4
np.random.seed( 0 )

%timeit np.random.choice( n**2, k * n, replace=True )  # 536 µs ± 1.58 µs
%timeit np.random.choice( n**2, k * n, replace=False ) # 6.1 s ± 9.91 ms

# https://docs.scipy.org/doc/numpy/reference/random/index.html
randomstate = np.random.default_rng( 0 )
%timeit randomstate.choice( n**2, k * n, replace=False, shuffle=False )  # 766 µs ± 2.18 µs
%timeit randomstate.choice( n**2, k * n, replace=False, shuffle=True )   # 1.05 ms ± 1.41 µs

%timeit random.sample( range( n**2 ), k * n )          # 47.3 ms ± 134 µs

(为什么从 10000^2 中选择 40000?要生成大型 scipy.sparse.random 矩阵——scipy 1.4.1 使用np.random.choice( replace=False ),slooooow。)

向 numpy.random 人致敬。

于 2011-12-14T14:08:51.147 回答
1

您也可以通过排序获得此信息:

random_numbers = np.random.random([num_samples, max_int])
samples = np.argsort(random_numbers, axis=1)
于 2018-10-23T11:20:21.740 回答
0

可以使用 Python 设置列表转换。可以得到 0 到 20 之间的 10 个随机不重复数:

import random
numbers=set()
while(len(numbers)<10):
    numbers.add(random.randint(0,20))

numbers=list(numbers)
random.shuffle(numbers)
print(numbers)
于 2020-12-01T10:20:32.583 回答
-3

只需生成一个包含所需数字范围的数组,然后通过重复将随机数字与数组中的第 0 个元素交换来打乱它们。这会产生一个不包含重复值的随机序列。

于 2011-12-14T13:59:33.637 回答