Non-repetitive random number in numpy
-
16-03-2021 - |
문제
How can I generate non-repetitive random numbers in numpy?
list = np.random.random_integers(20,size=(10))
해결책
numpy.random.Generator.choice
offers a replace
argument to sample without replacement:
from numpy.random import default_rng
rng = default_rng()
numbers = rng.choice(20, size=10, replace=False)
If you're on a pre-1.17 NumPy, without the Generator
API, you can use random.sample()
from the standard library:
print(random.sample(range(20), 10))
You can also use numpy.random.shuffle()
and slicing, but this will be less efficient:
a = numpy.arange(20)
numpy.random.shuffle(a)
print a[:10]
There's also a replace
argument in the legacy numpy.random.choice
function, but this argument was implemented inefficiently and then left inefficient due to random number stream stability guarantees, so its use isn't recommended. (It basically does the shuffle-and-slice thing internally.)
다른 팁
I think numpy.random.sample
doesn't work right, now. This is my way:
import numpy as np
np.random.choice(range(20), 10, replace=False)
Years later, some timeits for choosing 40000 out of 10000^2 (Numpy 1.8.1, imac 2.7 GHz):
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
(Why choose 40000 out of 10000^2 ?
To generate large
scipy.sparse.random
matrices -- scipy 1.4.1 uses np.random.choice( replace=False )
, slooooow.)
Tip of the hat to numpy.random people.
You can get this by sorting as well:
random_numbers = np.random.random([num_samples, max_int])
samples = np.argsort(random_numbers, axis=1)
Python set-list conversion can be used. 10 random non repetitive numbers between 0 and 20 can be obtained as:
import random
numbers=set()
while(len(numbers)<10):
numbers.add(random.randint(0,20))
numbers=list(numbers)
random.shuffle(numbers)
print(numbers)
Simply generate an array that contains the required range of numbers, then shuffle them by repeatedly swapping a random one with the 0th element in the array. This produces a random sequence that doesn't contain duplicate values.