2010-01-21 2 views
6

Я пытаюсь выбрать определенные элементы столбца для каждой строки массива numpy. Например, в следующем примере:Выбор определенного столбца в каждой строке из массива

In [1]: a = np.random.random((3,2)) 
Out[1]: 
array([[ 0.75670668, 0.1283942 ], 
     [ 0.51326555, 0.59378083], 
     [ 0.03219789, 0.53612603]]) 

Я хотел бы, чтобы выбрать первый элемент первой строки, второй элемент второго ряда, а первый элемент третьего ряда. Так что я попытался сделать следующее:

In [2]: b = np.array([0,1,0]) 

In [3]: a[:,b] 

Но это производит следующий вывод:

Out[3]: 
array([[ 0.75670668, 0.1283942 , 0.75670668], 
     [ 0.51326555, 0.59378083, 0.51326555], 
     [ 0.03219789, 0.53612603, 0.03219789]]) 

, который явно не то, что я ищу. Есть ли простой способ сделать то, что я хотел бы сделать, не используя циклы?

ответ

8

Вы можете использовать:

a[np.arange(3), (0,1,0)] 

в вашем примере выше.

+0

Действительно. * Slicing * сохраняет данную ось как есть, тогда как то, что вы хотели по обоим измерениям, называется * причудливой индексацией * в документации. – dwf

+0

Вправо. Например, 'a [0: 2,0: 2]' и 'a [[0,1], [0,1]]' возвращают разные вещи. –

2

Это не так много, как попытка документировать это. Для ответа на данный вопрос, мы имеем:

>>> import numpy as np 
>>> A = np.array(range(6)) 
>>> A 
array([0, 1, 2, 3, 4, 5]) 
>>> A.shape = (3,2) 
>>> A 
array([[0, 1], 
     [2, 3], 
     [4, 5]]) 
>>> A[(0,1,2),(0,1,0)] 
array([0, 3, 4]) 

Указание списка (или кортеж) отдельных строк и столбцов координат позволяет причудливой индексации массива. Первый пример в комментарии выглядит схожим поначалу, но индексы являются срезами. Они не распространяются на весь ассортимент, а форма массива, возвращенного отличается:

>>> A[0:2,0:2] 
array([[0, 1], 
     [2, 3]]) 

Для второго примера в комментарии

>>> A[[0,1],[0,1]] 
array([0, 3]) 

Таким образом, кажется, что ломтики различаются, но за исключением этого, независимо от того, как строятся индексы, вы можете указать кортеж или список (значения x, y-значения) и восстановить эти конкретные элементы из массива.

3

ОК, только чтобы уточнить здесь, позволяет сделать простой пример

A=diag(arange(0,10,1)) 

дает

array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
     [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], 
     [0, 0, 2, 0, 0, 0, 0, 0, 0, 0], 
     [0, 0, 0, 3, 0, 0, 0, 0, 0, 0], 
     [0, 0, 0, 0, 4, 0, 0, 0, 0, 0], 
     [0, 0, 0, 0, 0, 5, 0, 0, 0, 0], 
     [0, 0, 0, 0, 0, 0, 6, 0, 0, 0], 
     [0, 0, 0, 0, 0, 0, 0, 7, 0, 0], 
     [0, 0, 0, 0, 0, 0, 0, 0, 8, 0], 
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 9]]) 

затем

A[0][0:4] 

дает

array([0, 0, 0, 0]) 

что первый ряд, элементы от 0 до 3. Но

A[0:4][1] 

не дает первые 4 строки, 2-й элемент в каждой из них. Вместо этого мы получаем

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

i.e вся вторая колонка.

A[0:4,1] 

дает

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

Я уверен, что есть очень хорошая причина для этого, и которая имеет смысл для программистов , но для тех из нас, непосвященных в этой великой религии это может быть довольно запутанным ,

+0

A [0: 4] создает новый массив формы (4,10). С A [0: 4, y] вы запрашиваете второе измерение массива, тогда как для A [0: 4] [x] вы запрашиваете первое измерение нового массива! Вы можете записать это A [0: 4,:] [1 ,:], если это поможет вам увидеть, когда запрашивают dim 1 или dim 2 – bendaizer

+0

Использование diag в конечном итоге делает это более запутанным для вас самих и для других, потому что на самом деле 'A [ 0: 4] [1] 'дал вам второй * ряд *, а не второй столбец. –