Numpy: ottiene un set casuale di righe dall'array 2D


160

Ho un array 2D molto grande che assomiglia a questo:

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

Usando numpy, c'è un modo semplice per ottenere un nuovo array 2D con, ad esempio, 2 righe casuali dall'array iniziale a(senza sostituzione)?

per esempio

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

8
è sciocco avere una domanda per la sostituzione e una senza, dovresti solo consentire entrambe le risposte e in effetti incoraggiare entrambe le risposte.
Pinocchio,

Risposte:


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

Mettendolo insieme per un caso generale:

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

Per non sostituzione (numpy 1.7.0+):

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

Non credo ci sia un buon modo per generare un elenco casuale senza sostituzione prima dell'1.7. Forse puoi impostare una piccola definizione che garantisce che i due valori non siano uguali.


4
Forse non c'è un buon modo, ma un modo altrettanto buono np.random.choice, e cioè np.random.permutation(A.shape[0])[:2], in realtà non è eccezionale, ma questo è ciò che np.random.choicein questo momento ... o se non ti interessa cambiare l'array in posto,np.random.shuffle
seberg

1
Prima di numpy 1.7, usa random .sample (xrange (10), 2)
denis

3
perché stai nominando le variabili A e B e altro? rende più difficile la lettura.
Pinocchio,

48

Questo è un vecchio post, ma questo è ciò che funziona meglio per me:

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

cambia la sostituzione = False in True per ottenere la stessa cosa, ma con la sostituzione.


2
@SalvadorDali Ho modificato il post di Hezi per non scegliere con la sostituzione. Una volta che la modifica è sottoposta a peer review, vedrai il replace=Falseparametro aggiunto a choice.
0x24a537r9,

8
@ 0x24a537r9 non dovresti farlo. Questa è la sua risposta e tu la cambi. Se vuoi - aggiungi la tua risposta e non modificare le risposte di altre persone che alterano in modo significativo la risposta
Salvador Dali

@SalvadorDali perché no?
Scott,

25

Un'altra opzione è quella di creare una maschera casuale se si desidera semplicemente sottocampionare i dati di un determinato fattore. Supponiamo di voler sottocampionare fino al 25% del mio set di dati originale, che è attualmente contenuto nell'array 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])

Ora puoi chiamare data_arr[mask]e restituire ~ 25% delle righe, campionate casualmente.


Potresti voler aggiungere replace = Falsese non vuoi campionare con la sostituzione.
Sarah

La sostituzione @Sarah non è un problema con questo metodo di campionamento perché viene restituito un valore Vero / Falso per ogni posizione in data_arr. Nel mio esempio, un ~ 25% casuale delle posizioni sarà Truee quelle posizioni verranno campionate da data_arr.
Isosceleswheel

10

Questa è una risposta simile a quella fornita da Hezi Rasheff, ma semplificata in modo che gli utenti più recenti di Python capiscano cosa sta succedendo (ho notato che molti nuovi studenti di datascience raccolgono campioni casuali nei modi più strani perché non sanno cosa stanno facendo in Python).

Puoi ottenere un numero di indici casuali dal tuo array usando:

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

È quindi possibile utilizzare lo slicing con l'array numpy per ottenere i campioni in quegli indici:

A[indices]

Questo ti darà il numero specificato di campioni casuali dai tuoi dati.


5

Vedo che è stata suggerita la permutazione. In effetti può essere trasformato in una riga:

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

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


2

Se si desidera generare più sottoinsiemi casuali di righe, ad esempio se si sta eseguendo 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, :]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.