2016-06-18 26 views
5

Mam następujący kod w Pythonie (numpy tablicy lub scipy.sparse.matrices), to działa:Krótsza wersja tego numpy tablicy indeksowania

X[a,:][:,b] 

Ale nie wygląda elegancko. "a" i "b" są 1-D boolowską maską.

'a' mają tą samą długość jak X.shape [0] i 'b' ma taką samą długość jak X.shape [1]

że próbował X[a,b] ale to nie działa.

Co próbuję osiągnąć, to wybrać poszczególne wiersze i kolumny w tym samym czasie. Na przykład wybierz wiersz 0,7,8, a następnie z tego wyniku wybierz wszystkie wiersze z kolumny 2,3,4

W jaki sposób uczynisz to krótszym i bardziej eleganckim?

+0

.... 'x [A: b] '? – Divakar

+0

Nie, to jest matryca 2D. – off99555

+0

Czy używasz macierzy NumPy lub NumPy? – Divakar

Odpowiedz

5

Można użyć np.ix_ dla takiego broadcasted indexing, jak tak -

X[np.ix_(a,b)] 

Choć to nie będzie krótsza niż oryginalnego kodu, ale miejmy nadzieję, powinno być szybsze. Dzieje się tak dlatego, że unikamy wyjścia pośredniego, tak jak z oryginalnym kodem, który utworzył X[a,:] z jednym cięciem, a następnie kolejnym cięciem X[a,:][:,b], aby dać nam ostateczny wynik.

Ta metoda działałaby również dla a i b zarówno jako tablice int, jak i boolean.

Przykładowy przebieg

In [141]: X = np.random.randint(0,99,(6,5)) 

In [142]: m,n = X.shape 

In [143]: a = np.in1d(np.arange(m),np.random.randint(0,m,(m))) 

In [144]: b = np.in1d(np.arange(n),np.random.randint(0,n,(n))) 

In [145]: X[a,:][:,b] 
Out[145]: 
array([[17, 81, 64], 
     [87, 16, 54], 
     [98, 22, 11], 
     [26, 54, 64]]) 

In [146]: X[np.ix_(a,b)] 
Out[146]: 
array([[17, 81, 64], 
     [87, 16, 54], 
     [98, 22, 11], 
     [26, 54, 64]]) 

testu Czas trwania

In [147]: X = np.random.randint(0,99,(600,500)) 

In [148]: m,n = X.shape 

In [149]: a = np.in1d(np.arange(m),np.random.randint(0,m,(m))) 

In [150]: b = np.in1d(np.arange(n),np.random.randint(0,n,(n))) 

In [151]: %timeit X[a,:][:,b] 
1000 loops, best of 3: 1.74 ms per loop 

In [152]: %timeit X[np.ix_(a,b)] 
1000 loops, best of 3: 1.24 ms per loop 
+0

W moim przypadku "a" i "b" są maską logiczną. – off99555

+0

Sprawdź wyjście 'ix_', aby zobaczyć, jak można to zrobić bez niego. – hpaulj

+1

'np.ix_' stosuje' np.nonzero' do argumentów logicznych, konwertując je do indeksów. – hpaulj