Numpy: Obtenez un ensemble aléatoire de lignes à partir d'un tableau 2D

160

J'ai un très grand tableau 2D qui ressemble à ceci:

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

En utilisant numpy, existe-t-il un moyen simple d'obtenir un nouveau tableau 2D avec, par exemple, 2 lignes aléatoires du tableau initial a(sans remplacement)?

par exemple

b=
[[a4,  b4,  c4],
 [a99, b99, c99]]
gha
la source
8
c'est idiot d'avoir une question une pour le remplacement et une sans, vous devriez simplement permettre les deux réponses et en fait encourager les deux réponses.
Pinocchio

Réponses:

195
>>> 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]])

Mettre en place pour un cas général:

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

Pour non remplacement (numpy 1.7.0+):

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

Je ne pense pas qu'il existe un bon moyen de générer une liste aléatoire sans remplacement avant la 1.7. Vous pouvez peut-être configurer une petite définition qui garantit que les deux valeurs ne sont pas les mêmes.

Daniel
la source
4
Il n'y a peut-être pas un bon moyen, mais un moyen qui est tout aussi bon que np.random.choice, et qui est np.random.permutation(A.shape[0])[:2], en fait, ce n'est pas génial, mais c'est ce qui se passe np.random.choiceen ce moment ... ou si vous ne vous souciez pas de changer votre tableau en place,np.random.shuffle
seberg
1
Avant numpy 1.7, utilisez random .sample (xrange (10), 2)
denis
3
pourquoi nommez-vous vos variables A et B et tout? cela rend la lecture plus difficile.
Pinocchio
48

C'est un ancien article, mais c'est ce qui fonctionne le mieux pour moi:

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

changez le replace = False en True pour obtenir la même chose, mais avec remplacement.

Hezi Resheff
la source
2
@SalvadorDali J'ai édité le message de Hezi pour ne pas choisir le remplacement. Une fois la modification révisée par les pairs, vous verrez le replace=Falseparamètre ajouté à choice.
0x24a537r9
8
@ 0x24a537r9 vous ne devriez pas faire cela. C'est sa réponse et vous la changez. Si vous voulez - ajoutez votre réponse et ne changez pas les réponses d'autres personnes qui modifie considérablement la réponse
Salvador Dali
@SalvadorDali pourquoi pas?
Scott le
25

Une autre option consiste à créer un masque aléatoire si vous souhaitez simplement sous-échantillonner vos données d'un certain facteur. Dites que je veux sous-échantillonner à 25% de mon ensemble de données d'origine, qui est actuellement contenu dans le tableau 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])

Vous pouvez désormais appeler data_arr[mask]et renvoyer ~ 25% des lignes, échantillonnées au hasard.

roue isocèle
la source
Vous pouvez ajouter replace = Falsesi vous ne voulez pas d'échantillonnage avec remplacement.
Sarah il y a
@Sarah Replacement n'est pas un problème avec cette méthode d'échantillonnage car une valeur True / False est renvoyée pour chaque position dans data_arr. Dans mon exemple, environ 25% des positions seront aléatoires Trueet ces positions sont échantillonnées data_arr.
roue isocèle
10

C'est une réponse similaire à celle fournie par Hezi Rasheff, mais simplifiée pour que les nouveaux utilisateurs de python comprennent ce qui se passe (j'ai remarqué que de nombreux nouveaux étudiants en science des données récupèrent des échantillons aléatoires de la manière la plus étrange car ils ne savent pas ce qu'ils font en python).

Vous pouvez obtenir un certain nombre d'indices aléatoires de votre tableau en utilisant:

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

Vous pouvez ensuite utiliser le découpage avec votre tableau numpy pour obtenir les échantillons à ces indices:

A[indices]

Cela vous permettra d'obtenir le nombre spécifié d'échantillons aléatoires à partir de vos données.

CB Madsen
la source
5

Je vois que la permutation a été suggérée. En fait, il peut être composé d'une seule ligne:

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

array([[0, 3, 0],
       [3, 1, 2]])
orli
la source
4

Si vous avez besoin des mêmes lignes mais juste d'un échantillon aléatoire, alors,

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

Ici, x doit être un 'int' définissant le nombre de lignes que vous souhaitez sélectionner au hasard.

Ankit Agrawal
la source
4
Cela ne fonctionne que si old_arrayest une séquence ou un ensemble, pas un tableau numpy [lien] ( docs.python.org/3/library/random.html#functions-for-sequences )
leermeester
2

Si vous souhaitez générer plusieurs sous-ensembles aléatoires de lignes, par exemple si vous faites 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
la source