Usiłuję wybrać określone kolumny na wiersz NumPy
macierzy.
Załóżmy, że mam następującą macierz, którą nazwałbym X
:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
Mam też list
indeksy kolumn w każdym wierszu, które nazwałbym Y
:
[1, 0, 2]
Muszę uzyskać wartości:
[2]
[4]
[9]
Zamiast a list
z indeksami Y
mogę również utworzyć macierz o tym samym kształcie, w X
którym każda kolumna ma wartość bool
/ int
w zakresie 0-1, wskazując, czy jest to wymagana kolumna.
[0, 1, 0]
[1, 0, 0]
[0, 0, 1]
Wiem, że można to zrobić, wykonując iterację po tablicy i wybierając potrzebne wartości kolumn. Jednak będzie to wykonywane często na dużych tablicach danych i dlatego musi działać tak szybko, jak to tylko możliwe.
Zastanawiałem się więc, czy jest lepsze rozwiązanie?
Dziękuję Ci.
python
python-2.7
numpy
Zee
źródło
źródło
Odpowiedzi:
Jeśli masz tablicę logiczną, możesz dokonać bezpośredniego wyboru na podstawie tego:
>>> a = np.array([True, True, True, False, False]) >>> b = np.array([1,2,3,4,5]) >>> b[a] array([1, 2, 3])
Aby postępować zgodnie z początkowym przykładem, możesz wykonać następujące czynności:
>>> a = np.array([[1,2,3], [4,5,6], [7,8,9]]) >>> b = np.array([[False,True,False],[True,False,False],[False,False,True]]) >>> a[b] array([2, 4, 9])
Możesz również dodać
arange
i dokonać bezpośredniego wyboru, ale w zależności od tego, jak generujesz tablicę boolowską i jak wygląda Twój kod YMMV.>>> a = np.array([[1,2,3], [4,5,6], [7,8,9]]) >>> a[np.arange(len(a)), [1,0,2]] array([2, 4, 9])
Mam nadzieję, że to pomoże. Daj mi znać, jeśli masz więcej pytań.
źródło
arange
. Było to dla mnie szczególnie przydatne do pobierania różnych bloków z wielu macierzy (czyli w zasadzie przypadek 3D w tym przykładzie)arange
zamiast:
? Wiem, że twój sposób działa, a mój nie, ale chciałbym zrozumieć, dlaczego.:
składnia nie działa w ten sam sposób.:
z zaawansowanym indeksowaniem oznacza: „dla każdej podprzestrzeni:
zastosuj podane zaawansowane indeksowanie”. Czy moje rozumienie jest prawidłowe?Możesz zrobić coś takiego:
In [7]: a = np.array([[1, 2, 3], ...: [4, 5, 6], ...: [7, 8, 9]]) In [8]: lst = [1, 0, 2] In [9]: a[np.arange(len(a)), lst] Out[9]: array([2, 4, 9])
Więcej o indeksowaniu tablic wielowymiarowych: http://docs.scipy.org/doc/numpy/user/basics.indexing.html#indexing-multi-dimensional-arrays
źródło
:
spowoduje wyświetlenie wielulen(a)
razy wyników, zamiast tego wskazanie indeksu każdego wiersza spowoduje wydrukowanie oczekiwanych wyników.Prosty sposób może wyglądać następująco:
In [1]: a = np.array([[1, 2, 3], ...: [4, 5, 6], ...: [7, 8, 9]]) In [2]: y = [1, 0, 2] #list of indices we want to select from matrix 'a'
range(a.shape[0])
wróciarray([0, 1, 2])
In [3]: a[range(a.shape[0]), y] #we're selecting y indices from every row Out[3]: array([2, 4, 9])
źródło
W najnowszych
numpy
wersjach dodanotake_along_axis
(iput_along_axis
), który czyści to indeksowanie w sposób przejrzysty.In [101]: a = np.arange(1,10).reshape(3,3) In [102]: b = np.array([1,0,2]) In [103]: np.take_along_axis(a, b[:,None], axis=1) Out[103]: array([[2], [4], [9]])
Działa tak samo jak:
In [104]: a[np.arange(3), b] Out[104]: array([2, 4, 9])
ale z inną obsługą osi. Jest szczególnie ukierunkowany na zastosowanie wyników
argsort
iargmax
.źródło
Możesz to zrobić za pomocą iteratora. Lubię to:
np.fromiter((row[index] for row, index in zip(X, Y)), dtype=int)
Czas:
N = 1000 X = np.zeros(shape=(N, N)) Y = np.arange(N) #@Aशwini चhaudhary %timeit X[np.arange(len(X)), Y] 10000 loops, best of 3: 30.7 us per loop #mine %timeit np.fromiter((row[index] for row, index in zip(X, Y)), dtype=int) 1000 loops, best of 3: 1.15 ms per loop #mine %timeit np.diag(X.T[Y]) 10 loops, best of 3: 20.8 ms per loop
źródło
np.diag(X.T[Y])
jest taki wolny ... Alenp.diag(X.T)
jest taki szybki (10us). Nie wiem dlaczego.Innym sprytnym sposobem jest najpierw transpozycja tablicy, a następnie indeksowanie. Na koniec wybierz przekątną, to zawsze właściwa odpowiedź.
X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) Y = np.array([1, 0, 2, 2]) np.diag(X.T[Y])
Krok po kroku:
Oryginalne tablice:
>>> X array([[ 1, 2, 3], [ 4, 5, 6], [ 7, 8, 9], [10, 11, 12]]) >>> Y array([1, 0, 2, 2])
Transpozycja, aby umożliwić prawidłowe indeksowanie.
>>> X.T array([[ 1, 4, 7, 10], [ 2, 5, 8, 11], [ 3, 6, 9, 12]])
Uzyskaj wiersze w kolejności Y.
>>> X.T[Y] array([[ 2, 5, 8, 11], [ 1, 4, 7, 10], [ 3, 6, 9, 12], [ 3, 6, 9, 12]])
Przekątna powinna teraz stać się wyraźna.
>>> np.diag(X.T[Y]) array([ 2, 4, 9, 12]
źródło