Numpy: obtenga un conjunto aleatorio de filas de la matriz 2D


159

Tengo una matriz 2D muy grande que se parece a esto:

a=
[[a1, b1, c1],
 [a2, b2, c2],
 ...,
 [an, bn, cn]]

Usando numpy, ¿hay una manera fácil de obtener una nueva matriz 2D con, por ejemplo, 2 filas aleatorias de la matriz inicial a(sin reemplazo)?

p.ej

b=
[[a4,  b4,  c4],
 [a99, b99, c99]]

8
Es una tontería tener una pregunta de reemplazo y otra sin preguntas, solo debe permitir ambas respuestas y, de hecho, alentar ambas respuestas.
Pinocho

Respuestas:


193
>>> A = np.random.randint(5, size=(10,3))
>>> A
array([[1, 3, 0],
       [3, 2, 0],
       [0, 2, 1],
       [1, 1, 4],
       [3, 2, 2],
       [0, 1, 0],
       [1, 3, 1],
       [0, 4, 1],
       [2, 4, 2],
       [3, 3, 1]])
>>> idx = np.random.randint(10, size=2)
>>> idx
array([7, 6])
>>> A[idx,:]
array([[0, 4, 1],
       [1, 3, 1]])

Poniéndolo junto para un caso general:

A[np.random.randint(A.shape[0], size=2), :]

Para no reemplazo (numpy 1.7.0+):

A[np.random.choice(A.shape[0], 2, replace=False), :]

No creo que haya una buena manera de generar una lista aleatoria sin reemplazo antes de 1.7. Quizás pueda configurar una pequeña definición que garantice que los dos valores no sean iguales.


44
Tal vez no haya una buena manera, pero es una manera tan buena como np.random.choice, y es que en np.random.permutation(A.shape[0])[:2]realidad no es genial, pero eso es lo que hay np.random.choiceen este momento ... o si no le importa cambiar su matriz en lugar,np.random.shuffle
seberg

1
Antes de numpy 1.7, use .sample aleatorio (xrange (10), 2)
denis

3
¿Por qué nombras tus variables A y B y esas cosas? hace que sea más difícil de leer.
Pinocho

48

Esta es una publicación antigua, pero esto es lo que funciona mejor para mí:

A[np.random.choice(A.shape[0], num_rows_2_sample, replace=False)]

cambie el replace = False a True para obtener lo mismo, pero con reemplazo.


2
@SalvadorDali He editado la publicación de Hezi para no elegir con reemplazo. Una vez que la edición sea revisada por pares, verá el replace=Falseparámetro agregado a choice.
0x24a537r9

8
@ 0x24a537r9 no deberías hacer esto. Esta es su respuesta y la cambias. Si lo desea, agregue su respuesta y no cambie las respuestas de otras personas que alteren significativamente la respuesta
Salvador Dali

@SalvadorDali ¿por qué no?
Scott,

25

Otra opción es crear una máscara aleatoria si solo desea reducir la muestra de datos por un determinado factor. Digamos que quiero reducir la muestra al 25% de mi conjunto de datos original, que actualmente se encuentra en la matriz data_arr:

# generate random boolean mask the length of data
# use p 0.75 for False and 0.25 for True
mask = numpy.random.choice([False, True], len(data_arr), p=[0.75, 0.25])

Ahora puede llamar data_arr[mask]y devolver ~ 25% de las filas, muestreadas al azar.


10

Esta es una respuesta similar a la que proporcionó Hezi Rasheff, pero simplificada para que los usuarios más nuevos de Python entiendan lo que está sucediendo (noté que muchos nuevos estudiantes de ciencia de datos obtienen muestras aleatorias de la manera más extraña porque no saben lo que están haciendo en Python).

Puede obtener varios índices aleatorios de su matriz utilizando:

indices = np.random.choice(A.shape[0], amount_of_samples, replace=False)

Luego puede usar el corte en rebanadas con su matriz numpy para obtener las muestras en esos índices:

A[indices]

Esto le dará el número especificado de muestras aleatorias de sus datos.


5

Veo que se ha sugerido la permutación. De hecho, se puede convertir en una línea:

>>> A = np.random.randint(5, size=(10,3))
>>> np.random.permutation(A)[:2]

array([[0, 3, 0],
       [3, 1, 2]])


2

Si desea generar múltiples subconjuntos aleatorios de filas, por ejemplo, si está haciendo RANSAC.

num_pop = 10
num_samples = 2
pop_in_sample = 3
rows_to_sample = np.random.random([num_pop, 5])
random_numbers = np.random.random([num_samples, num_pop])
samples = np.argsort(random_numbers, axis=1)[:, :pop_in_sample]
# will be shape [num_samples, pop_in_sample, 5]
row_subsets = rows_to_sample[samples, :]
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.