python - sacar - Matriz aleatoria binaria con una proporción específica de unos?
random letras python (5)
¿Cuál es la forma eficiente (probablemente vectorizada con la terminología de Matlab) de generar un número aleatorio de ceros y unos con una proporción específica? Especialmente con Numpy?
Como mi caso es especial para 1/3
, mi código es:
import numpy as np
a=np.mod(np.multiply(np.random.randomintegers(0,2,size)),3)
Pero, ¿hay alguna función incorporada que pueda manejar esto de manera más eficiente, al menos para la situación de K/N
donde K y N son números naturales?
Otro enfoque más, usando 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])
Puedes usar numpy.random.binomial
. Por ejemplo, supongamos que frac
es la proporción de unos:
In [50]: frac = 0.15
In [51]: sample = np.random.binomial(1, frac, size=10000)
In [52]: sample.sum()
Out[52]: 1567
Si entiendo tu problema correctamente, podrías obtener ayuda con 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.])
Simple one-liner: puede evitar el uso de listas de enteros y distribuciones de probabilidad, que son poco intuitivas y excesivas para este problema en mi opinión, simplemente trabajando con bool
s primero y luego lanzando a int
si es necesario (aunque dejándolo como un bool
array debería funcionar en la mayoría de los casos).
>>> 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])
Una forma simple de hacer esto sería generar primero un ndarray
con la proporción de ceros y unos que desee:
>>> 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])
Luego puedes simplemente shuffle
la matriz, haciendo que la distribución sea aleatoria:
>>> 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])
Tenga en cuenta que este enfoque le dará la proporción exacta de ceros / unos que solicite, a diferencia del enfoque binomial. Si no necesita la proporción exacta, entonces el enfoque binomial funcionará bien.