2014-12-15 26 views
8

Jaki jest najlepszy sposób, aby skutecznie permutować zawartość każdej kolumny w tablicy numpy?Najlepszy sposób na permutację zawartości każdej kolumny w numpy

Co mam coś takiego jak:

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

Niedawna dyskusja (https://www.marshut.net/kpwyti/request-for-enhancement-to-numpy-random-shuffle.html) na płytach rozwojowych 'numpy' wskazuje na tę funkcję dodawaną , ufnie. Sugeruje to również, że nie ma zadowalającego sposobu robienia tego z tym, co już mamy w "numpy" 1.9. – jme

Odpowiedz

6

Jeśli tablica jest wielowymiarowa, np.random.permutation permutacji wzdłuż pierwszej osi (kolumny) domyślnie:

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

Jednak to tasuje indeksy wierszy, a więc każda kolumna ma takie samo (losowe) porządkowanie.

Najprostszym sposobem tasowanie każdą kolumnę niezależnie może być do pętli na kolumnach i używać np.random.shuffle shuffle każdy w lokalu:

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

Co daje, na przykład:

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

ten Metoda może być użyteczna, jeśli masz bardzo dużą tablicę, której nie chcesz kopiować, ponieważ permutacja każdej kolumny jest wykonywana w miejscu. Z drugiej strony, nawet proste pętle Pythona mogą być bardzo powolne i istnieją szybsze metody NumPy, takie jak te udostępnione przez @jme.

5

Oto kolejny sposób w ten sposób:

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] 

Szybki test:

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

Chodzi o to, aby wygenerować kilka liczb losowych, a następnie argsort je w każdej kolumnie niezależnie. Powoduje to losową permutację indeksów każdej kolumny.

Należy zauważyć, że ma to nieoptymalną asymptotyczną złożoność czasu, ponieważ sortowanie zajmuje czas O(n m log m) dla tablicy o rozmiarze m x n. Ale ponieważ pętle Pythona for są dość powolne, faktycznie uzyskuje się lepszą wydajność dla wszystkich, ale bardzo wysokich macierzy.