Was ist der effiziente (wahrscheinlich mit Matlab-Terminologie vektorisierte) Weg, um Zufallszahlen von Nullen und Einsen mit einem bestimmten Verhältnis zu erzeugen? Speziell bei Numpy?
Da mein Fall speziell für 1/3
ist, lautet mein Code:
import numpy as np
a=np.mod(np.multiply(np.random.randomintegers(0,2,size)),3)
Aber gibt es eine eingebaute Funktion, die dies zumindest für die Situation von K/N
, in der K und N natürliche Zahlen sind, effizienter handhaben könnte?
Noch ein anderer Ansatz mit np.random.choice
:
>>> np.random.choice([0, 1], size=(10,), p=[1./3, 2./3])
array([0, 1, 1, 1, 1, 0, 0, 0, 0, 0])
Ein einfacher Weg, dies zu tun, wäre, zuerst ein ndarray
mit dem Anteil von Nullen und Einsen zu generieren, den Sie möchten:
>>> import numpy as np
>>> N = 100
>>> K = 30 # K zeros, N-K ones
>>> arr = np.array([0] * K + [1] * (N-K))
>>> arr
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1])
Dann können Sie einfach das Array shuffle
machen und die Verteilung zufällig machen:
>>> np.random.shuffle(arr)
>>> arr
array([1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0,
1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1,
1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1,
1, 1, 1, 0, 1, 1, 1, 1])
Beachten Sie, dass dieser Ansatz Ihnen den exakten Anteil von Nullen/Einsen gibt, die Sie anfordern, im Gegensatz zum binomialen Ansatz. Wenn Sie nicht das genaue Verhältnis benötigen, funktioniert der binomische Ansatz gut.
Sie können numpy.random.binomial
verwenden. Z.B. Angenommen, frac
ist der Anteil von Einsen:
In [50]: frac = 0.15
In [51]: sample = np.random.binomial(1, frac, size=10000)
In [52]: sample.sum()
Out[52]: 1567
Wenn ich Ihr Problem richtig verstanden habe, könnten Sie Hilfe mit numpy.random.shuffle
>>> def Rand_bin_array(K, N):
arr = np.zeros(N)
arr[:K] = 1
np.random.shuffle(arr)
return arr
>>> Rand_bin_array(5,15)
array([ 0., 1., 0., 1., 1., 1., 0., 0., 0., 1., 0., 0., 0.,
0., 0.])
Einfacher Einzeiler: Sie können vermeiden, Listen mit ganzen Zahlen und Wahrscheinlichkeitsverteilungen zu verwenden, die meines Erachtens für dieses Problem unintuitiv und übertrieben sind, indem Sie einfach zuerst mit bool
s arbeiten und, falls erforderlich, in int
umwandeln (wenn auch als bool
-Array in den meisten Fällen arbeiten).
>>> import numpy as np
>>> np.random.random(9) < 1/3.
array([False, True, True, True, True, False, False, False, False])
>>> (np.random.random(36) < 1/3.).astype(int)
array([0, 0, 0, 0, 0, 1, 0, 0, 1])
Eine andere Möglichkeit, die genaue Anzahl von Einsen und Nullen zu ermitteln, besteht darin, Indizes ohne Ersetzung mit np.random.choice
Abzutasten:
arr_len = 30
num_ones = 8
arr = np.zeros(arr_len, dtype=int)
idx = np.random.choice(range(arr_len), num_ones, replace=False)
arr[idx] = 1
Aus:
arr
array([0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1,
0, 0, 0, 0, 0, 1, 0, 0])