2014-12-15 8 views
8

Qual è il modo migliore per permutare in modo efficiente il contenuto di ogni colonna in un array numpy?Il modo migliore per permutare il contenuto di ogni colonna numpy

Quello che ho è qualcosa di simile:

>>> arr = np.arange(16).reshape((4, 4)) 
>>> arr 
array([[ 0, 1, 2, 3], 
     [ 4, 5, 6, 7], 
     [ 8, 9, 10, 11], 
     [12, 13, 14, 15]]) 

>> # Shuffle each column independently to obtain something like 
array([[ 8, 5, 10, 7], 
     [ 12, 1, 6, 3], 
     [ 4, 9, 14, 11], 
     [ 0, 13, 2, 15]]) 
+2

Una recente [discussione] (https://www.marshut.net/kpwyti/request-for-enhancement-to-numpy-random-shuffle.html) sulle schede di sviluppo 'numpy' punta a questa funzionalità che viene aggiunta , fiduciosamente. Ciò suggerisce anche che non esiste un modo soddisfacente per farlo con ciò che abbiamo già disponibile in 'numpy' 1.9. – jme

risposta

6

Se l'array è multi-dimensionale, np.random.permutation permuta lungo il primo asse (colonne) per impostazione predefinita:

>>> np.random.permutation(arr) 
array([[ 4, 5, 6, 7], 
     [ 8, 9, 10, 11], 
     [ 0, 1, 2, 3], 
     [12, 13, 14, 15]]) 

Tuttavia, questa mescola il indici di riga e quindi ogni colonna ha lo stesso ordinamento (casuale).

Il modo più semplice di mischiare ogni colonna in modo indipendente potrebbe essere quello di un ciclo su colonne e utilizzare np.random.shuffle a mischiare ognuno al suo posto:

for i in range(arr.shape[1]): 
    np.random.shuffle(arr[:,i]) 

che dà, per esempio:

array([[12, 1, 14, 11], 
     [ 4, 9, 10, 7], 
     [ 8, 5, 6, 15], 
     [ 0, 13, 2, 3]]) 

Questo il metodo può essere utile se si dispone di un array molto grande che non si desidera copiare perché la permutazione di ogni colonna viene eseguita in posizione. D'altra parte, anche i semplici loop di Python possono essere molto lenti e ci sono metodi NumPy più veloci come quello fornito da @jme.

5

Ecco un altro modo di fare questo:

def permute_columns(x): 
    ix_i = np.random.sample(x.shape).argsort(axis=0) 
    ix_j = np.tile(np.arange(x.shape[1]), (x.shape[0], 1)) 
    return x[ix_i, ix_j] 

Un test rapido:

>>> x = np.arange(16).reshape(4,4) 
>>> permute_columns(x) 
array([[ 8, 9, 2, 3], 
     [ 0, 5, 10, 11], 
     [ 4, 13, 14, 7], 
     [12, 1, 6, 15]]) 

L'idea è quello di generare una serie di numeri casuali, poi argsort loro all'interno di ogni colonna in modo indipendente. Questo produce una permutazione casuale degli indici di ciascuna colonna.

Si noti che questo ha una complessità temporale asimmetrica sub-ottimale, poiché l'ordinamento richiede tempo O(n m log m) per un array di dimensioni m x n. Ma dal momento che i loop di Python for sono piuttosto lenti, si ottengono prestazioni migliori per tutte le matrici, ma molto alte.

Problemi correlati