Número aleatorio no repetitivo en numpy

88

¿Cómo puedo generar números aleatorios no repetitivos en numpy?

list = np.random.random_integers(20,size=(10))
Academia
fuente
¿Qué quieres decir con "no repetitivo"? ¿Que la secuencia de números aleatorios nunca se repite? Esto no es posible, ya que el estado del generador de números aleatorios debe caber en la memoria finita de una computadora. ¿O quiere decir que ningún número aparece dos veces?
Sven Marnach
5
No repetitivo significa que tiene una lista sin duplicados.
Polinomio
2
¿Quizás necesitas una permutación aleatoria? docs.scipy.org/doc/numpy/reference/generated/…
cyborg

Respuestas:

106

numpy.random.Generator.choiceofrece un replaceargumento para muestrear sin reemplazo:

from numpy.random import default_rng

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

Si está en un NumPy anterior a 1.17, sin la GeneratorAPI, puede usar random.sample()desde la biblioteca estándar:

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

También puede usar numpy.random.shuffle()y cortar, pero esto será menos eficiente:

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

También hay un replaceargumento en la numpy.random.choicefunción heredada , pero este argumento se implementó de manera ineficiente y luego se dejó ineficaz debido a las garantías de estabilidad del flujo de números aleatorios, por lo que no se recomienda su uso. (Básicamente hace la cosa de mezclar y cortar internamente).

Sven Marnach
fuente
1
print random.sample (range (20), 10) no funciona con Python 2.6 ?!
Academia
¿Verdad import random?
Sven Marnach
El problema se debió a una mala configuración de Pydev. Thks
Academia
1
¿Qué pasa si mi n no es 20, sino 1000000, pero solo necesito 10 números únicos de él, hay un enfoque más eficiente en la memoria?
mrgloom
2
@mrgloom En Python 3, random.sample(range(n), 10))será eficiente incluso para muy grandes n, ya que un rangeobjeto es solo un contenedor pequeño que almacena valores de inicio, parada y paso, pero no crea la lista completa de enteros. En Python 2, puede reemplazar rangecon xrangepara obtener un comportamiento similar.
Sven Marnach
107

Creo numpy.random.sampleque no funciona bien ahora. Esta es mi manera:

import numpy as np
np.random.choice(range(20), 10, replace=False)
strnam
fuente
25
En lugar de range(n)(o arange(n)) como primer argumento de choice, es equivalente a pasar n, por ejemplo choice(20, 10, replace=False).
Josh Bode
1
Tenga en cuenta que np.random.choice(a, size, replace=False)es muy lento para grandes a: en mi máquina, alrededor de 30 ms para a = 1M.
Matthew Rahtz
3
Para evitar problemas de tiempo y memoria para un nuso muy extenso numpy.random.Generator.choice(comenzando con numpy v1.17)
benbo
1
La principal desventaja que veo es que np.random.choice no tiene un parámetro de eje -> es solo para matrices 1d.
Moosefeather
3

Años más tarde, es hora de elegir 40000 de 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

(¿Por qué elegir 40000 de 10000 ^ 2 Para generar grandes? Scipy.sparse.random matrices - scipy 1.4.1 usos np.random.choice( replace=False )., Leeeentos)

Punta del sombrero para la gente numpy.random.

denis
fuente
1

Puede obtener esto ordenando también:

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

Simplemente genere una matriz que contenga el rango requerido de números, luego revuélvalos intercambiando repetidamente uno aleatorio con el elemento 0 de la matriz. Esto produce una secuencia aleatoria que no contiene valores duplicados.

Polinomio
fuente
2
Otra propiedad de la secuencia aleatoria resultante es que no es particularmente aleatoria .
Sven Marnach
@SvenMarnach: para la mayoría de los propósitos, sin embargo, es lo suficientemente aleatorio. Podría usar el enfoque de doble aleatorio si lo quisiera más aleatorio.
Polinomio
Esto es inutil. El OP puede usar llamadas a la biblioteca para hacerlo bien. Son más fáciles de usar, se ejecutan más rápido y son más legibles que una versión personalizada. No puedo pensar en ninguna razón por la que debería usar un algoritmo incorrecto aquí solo porque probablemente sea "lo suficientemente aleatorio", cuando usar el algoritmo correcto no tiene ninguna desventaja.
Sven Marnach
@SvenMarnach - Bastante justo. No sé numpy, así que solo estaba ofreciendo una posible solución.
Polinomio