Логическое индексирование, но оказывается какой-то другой операцией

#python #numpy

#python #numpy

Вопрос:

Я пытался выполнить логическое индексирование, но..

 np.random.randn(8).reshape((4,2))
Out[11]: 
array([[-1.13058416,  1.08397186],
       [-1.2730122 ,  0.78306498],
       [-0.05370502, -1.16723298],
       [ 1.01750955, -0.95029671]])

a=np.random.randn(8).reshape((4,2))

a[[2==3,3==0,0==0,1!=1]]
Out[13]: 
array([[ 0.18235299, -2.53482367],
       [ 0.18235299, -2.53482367],
       [-1.03752809, -2.2790847 ],
       [ 0.18235299, -2.53482367]])
 

Что только что произошло?
Я больше думал об индексации Bool. Что это за операция?
Я не прошу исправлять это для индексации Bool. Скорее, я спрашиваю, что происходит в этой операции? Это законно?

Комментарии:

1. Что это [2==3,3==0,0==0,1!=1] значит?

2. 2 == 3 интерпретируется как 0 (False), поэтому a[[2==3,3==0,0==0,1!=1]] эквивалентно a[[0,0,1,0]]

3. точно, произвольные числа только для генерации bool

4. У вас была возможность взглянуть на мой ответ?

5. @AndrasDeak Я читаю это сейчас. дайте мне когда-нибудь

Ответ №1:

Легко думать о ndarray s как list о буферизованных s. Трансляция и операции с массивами автоматически распространяются на списки, участвующие в этих операциях, поэтому вы можете добавить массив и список совместимых с трансляцией фигур, и numpy не будет пытаться объединить их (как это было бы с двумя списками).

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

 import numpy as np
A = np.random.rand(3,3)
A[0:1,0:1]
A[range(2),range(2)]
 

Первая представляет собой операцию нарезки и возвращает подматрицу размером 2 на 2. Последнее является случаем причудливого индексирования и возвращает только массив из 2 элементов, содержащий A[0,0] и A[1,1] .

Ваш вопрос связан с чем-то столь же странным: списки и массивы логических значений ведут себя по-разному при использовании в fancy indexing. Рассмотрим следующие два примера в соответствии с вашим вопросом:

 A = np.random.rand(4,2)
bool_index_list = [False, True, True, False]
bool_index_array = np.array(bool_index_list)
A[bool_index_list].shape
A[bool_index_array].shape
 

Первое возвращает (4,2) последнее (2,2) .

В первом случае, поскольку индекс равен a list , логические значения преобразуются в соответствующие целые числа, а результирующие значения [0,1,1,0] используются в качестве фактических индексов в матрице, возвращая строку [first,second,second,first] соответственно.

В последнем случае индекс array of dtype=bool используется так, как вы ожидаете: он используется как маска для игнорирования тех строк of A , для которых указан индекс False .

Примечания к выпуску numpy, среди прочего, указывают, что

В будущем логические массивы (такие как списки bools python) всегда будут обрабатываться как логические индексы, а логические скаляры (включая python True ) будут законным логическим индексом.

Соответственно, приведенные выше случаи индексации на основе списков дают мне следующее предупреждение в numpy 1.10.1:

Предупреждение на будущее: в будущем логические массивы-лайки будут обрабатываться как индекс логического массива

Итак, короткий ответ на ваш вопрос заключается в том, что это законно, но ненадолго. Придерживайтесь ndarray навороченной индексации, и на этом пути у вас не должно возникнуть никаких проблем.