Nicht repetitive Zufallszahl in numpy

87

Wie kann ich nicht repetitive Zufallszahlen in Numpy generieren?

list = np.random.random_integers(20,size=(10))
Akademie
quelle
Was meinst du mit "nicht repetitiv"? Dass die Folge von Zufallszahlen nie wiederkehrt? Dies ist nicht möglich, da der Zustand des Zufallszahlengenerators in den endlichen Speicher eines Computers passen muss. Oder meinst du damit, dass keine einzelne Zahl zweimal vorkommt?
Sven Marnach
5
Nicht repetitiv bedeutet, dass Sie eine Liste ohne Duplikate haben.
Polynom
2
Vielleicht brauchen Sie eine zufällige Permutation? docs.scipy.org/doc/numpy/reference/generated/…
Cyborg

Antworten:

104

numpy.random.Generator.choicebietet ein replaceArgument, um ersatzlos zu probieren:

from numpy.random import default_rng

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

Wenn Sie ein NumPy vor 1.17 ohne GeneratorAPI verwenden, können Sie Folgendes random.sample()aus der Standardbibliothek verwenden:

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

Sie können auch verwenden numpy.random.shuffle()und in Scheiben schneiden, dies ist jedoch weniger effizient:

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

Es gibt auch ein replaceArgument in der Legacy- numpy.random.choiceFunktion, aber dieses Argument wurde ineffizient implementiert und dann aufgrund von Stabilitätsgarantien für Zufallszahlenströme ineffizient gelassen, sodass seine Verwendung nicht empfohlen wird. (Grundsätzlich wird das Shuffle-and-Slice-Ding intern ausgeführt.)

Sven Marnach
quelle
1
print random.sample (Bereich (20), 10) funktioniert nicht mit Python 2.6?!
Academia
Hast du import random?
Sven Marnach
Das Problem war auf eine schlechte Pydev-Konfiguration zurückzuführen. Thks
Academia
1
Was ist, wenn mein n nicht 20 ist, sondern 1000000, aber ich nur 10 eindeutige Zahlen benötige? Gibt es einen speichereffizienteren Ansatz?
Mrgloom
2
@mrgloom In Python 3 ist random.sample(range(n), 10))es auch für sehr große Objekte effizient n, da ein rangeObjekt nur ein kleiner Wrapper ist, der Start-, Stopp- und Schrittwerte speichert, jedoch nicht die vollständige Liste der Ganzzahlen erstellt. In Python 2 können Sie ersetzen rangemit xrangeeinem ähnlichen Verhalten zu bekommen.
Sven Marnach
107

Ich denke, numpy.random.samplefunktioniert momentan nicht. Das ist mein Weg:

import numpy as np
np.random.choice(range(20), 10, replace=False)
strnam
quelle
25
Anstelle von range(n)(oder arange(n)) als erstem Argument von choiceist es gleichbedeutend mit nur bestanden n, z choice(20, 10, replace=False).
Josh Bode
1
Beachten Sie, dass dies np.random.choice(a, size, replace=False)für große Geräte sehr langsam ist a- auf meinem Computer etwa 30 ms für a = 1M.
Matthew Rahtz
3
Um Zeit- und Speicherprobleme bei sehr großer nNutzung zu vermeiden numpy.random.Generator.choice(beginnend mit numpy v1.17)
benbo
1
Der Hauptnachteil, den ich sehe, ist, dass np.random.choice keinen Achsenparameter hat -> es ist nur für 1d-Arrays.
Elchfeder
3

Jahre später einige Zeiträume für die Auswahl von 40000 aus 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

(Warum 40000 von 10000 ^ 2 wählen? Um große scipy.sparse.random- Matrizen zu generieren - scipy 1.4.1 verwendet np.random.choice( replace=False ), slooooow.)

Tipp des Hutes an numpy.random Leute.

denis
quelle
1

Sie können dies auch durch Sortieren erhalten:

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

Generieren Sie einfach ein Array, das den erforderlichen Zahlenbereich enthält, und mischen Sie diese, indem Sie wiederholt ein zufälliges mit dem 0. Element im Array austauschen. Dies erzeugt eine zufällige Sequenz, die keine doppelten Werte enthält.

Polynom
quelle
2
Eine weitere Eigenschaft der resultierenden Zufallssequenz ist, dass sie nicht besonders zufällig ist .
Sven Marnach
@SvenMarnach - Für die meisten Zwecke ist es jedoch zufällig genug. Er könnte den Doppel-Zufalls-Ansatz verwenden, wenn er es zufälliger haben wollte.
Polynom
Das ist sinnlos. Das OP kann Bibliotheksaufrufe verwenden, um es richtig zu machen. Sie sind einfacher zu verwenden, schneller auszuführen und besser lesbar als eine benutzerdefinierte Version. Ich kann mir keinen Grund vorstellen, warum ich hier einen falschen Algorithmus verwenden sollte, nur weil er wahrscheinlich "zufällig genug" ist, wenn die Verwendung des richtigen Algorithmus überhaupt keinen Nachteil hat.
Sven Marnach
@SvenMarnach - Fair genug. Ich kenne Numpy nicht, also habe ich nur eine mögliche Lösung angeboten.
Polynom