it-swarm.com.de

Binäres zufälliges Array mit einem bestimmten Anteil von Einsen?

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?

36
Cupitor

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])
52
Jaime

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.

18
mdml

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
15

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.])
4
Abhijit

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 bools 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])    
0

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])
0
joelostblom