Niepowtarzalna liczba losowa w numpy


88

Jak mogę wygenerować niepowtarzalne liczby losowe w numpy?

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

Co rozumiesz przez „niepowtarzalność”? Że sekwencja liczb losowych nigdy się nie powtarza? Nie jest to możliwe, ponieważ stan generatora liczb losowych musi mieścić się w skończonej pamięci komputera. Czy masz na myśli to, że żadna pojedyncza liczba nie występuje dwukrotnie?
— Sven Marnach

5
Niepowtarzalność oznacza, że ​​masz listę bez duplikatów.
— Wielomian

2
Może potrzebujesz losowej permutacji? docs.scipy.org/doc/numpy/reference/generated/ ...
— cyborg

Odpowiedzi:


106

numpy.random.Generator.choiceoferuje replaceargument do próbkowania bez wymiany:

from numpy.random import default_rng

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

Jeśli Generatorkorzystasz random.sample()z NumPy w wersji starszej niż 1.17, bez API, możesz użyć z biblioteki standardowej:

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

Możesz także użyć numpy.random.shuffle()i pokroić, ale będzie to mniej wydajne:

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

Istnieje również replaceargument w starszej numpy.random.choicefunkcji, ale ten argument został zaimplementowany nieefektywnie, a następnie pozostawił nieefektywny ze względu na gwarancje stabilności strumienia liczb losowych, więc jego użycie nie jest zalecane. (Zasadniczo robi to wewnętrznie tasuj i pokrój).


1
print random.sample (range (20), 10) nie działa z Pythonem 2.6 ?!
— Academia,

Zrobiłeś import random?
— Sven Marnach

Problem był spowodowany złą konfiguracją Pydeva. Dzięki
— Academia,

1
A jeśli moje n nie jest równe 20, ale takie jak 1000000, ale potrzebuję tylko 10 unikalnych liczb, czy istnieje podejście wydajniejsze pod względem pamięci?
— mrgloom,

2
@mrgloom W Pythonie 3 random.sample(range(n), 10))będzie wydajne nawet dla bardzo dużych n, ponieważ rangeobiekt jest tylko małym opakowaniem przechowującym wartości start, stop i step, ale nie tworzy pełnej listy liczb całkowitych. W Pythonie 2, można wymienić rangez xrangeaby uzyskać podobne zachowanie.
— Sven Marnach

107

Myślę, że numpy.random.sampleteraz nie działa dobrze. To jest mój sposób:

import numpy as np
np.random.choice(range(20), 10, replace=False)

25
Zamiast range(n)(lub arange(n)) jako pierwszego argumentu choice, jest to równoznaczne z przekazaniem n, np choice(20, 10, replace=False).
— Josh Bode

1
Zauważ, że np.random.choice(a, size, replace=False)jest to bardzo wolne dla dużych a- na moim komputerze około 30 ms dla a = 1M.
— Matthew Rahtz

3
Aby uniknąć problemów z czasem i pamięcią przy bardzo dużych nzastosowaniach numpy.random.Generator.choice(począwszy od numpy v1.17)
— benbo

1
Główną wadą, którą widzę, jest to, że np.random.choice nie ma parametru osi -> jest to tylko dla tablic 1d.
— Moosefeather

3

Lata później, trochę czasu na wybranie 40000 z 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

(Dlaczego 40000 z 10000 ^ 2 do generowania dużych? Scipy.sparse.random matryce - scipy 1.4.1 niej korzysta np.random.choice( replace=False )., Slooooow)

Końcówka kapelusza dla numpy.random people.


1

Możesz to również uzyskać, sortując:

random_numbers = np.random.random([num_samples, max_int])
samples = np.argsort(random_numbers, axis=1)

-3

Po prostu wygeneruj tablicę zawierającą wymagany zakres liczb, a następnie przetasuj je, wielokrotnie zamieniając losową z zerowym elementem tablicy. Daje to losową sekwencję, która nie zawiera zduplikowanych wartości.


2
Inną właściwością wynikowej sekwencji losowej jest to, że nie jest ona szczególnie losowa .
— Sven Marnach

@SvenMarnach - w większości przypadków jest jednak wystarczająco losowy. Mógłby zastosować podejście podwójnie losowe, gdyby chciał, żeby było bardziej losowe.
— Wielomian

To jest bezcelowe. OP może użyć wywołań biblioteki, aby zrobić to dobrze. Są łatwiejsze w użyciu, działają szybciej i są bardziej czytelne niż wersje niestandardowe. Nie przychodzi mi do głowy żaden powód, dla którego miałbym używać złego algorytmu, tylko dlatego, że jest on prawdopodobnie „wystarczająco losowy”, a użycie właściwego algorytmu nie ma żadnej wady.
— Sven Marnach,

@SvenMarnach - W porządku. Nie wiem, numpy, więc oferowałem tylko potencjalne rozwiązanie.
— Wielomian
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.