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]]
gha
fuente
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.

Daniel
fuente
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.

Hezi Resheff
fuente
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.

rueda isósceles
fuente
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.

CB Madsen
fuente
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]])
orli
fuente
4

Si necesita las mismas filas pero solo una muestra aleatoria, entonces,

import random
new_array = random.sample(old_array,x)

Aquí x, tiene que ser un 'int' que define el número de filas que desea elegir al azar.

Ankit Agrawal
fuente
44
Esto solo funciona si old_arrayes una secuencia o un conjunto, no una matriz numpy [enlace] ( docs.python.org/3/library/random.html#functions-for-sequences )
leermeester
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, :]
Ben
fuente