Расширенный нарезка при передаче списка вместо кортежа в numpy

В документах говорится (подчеркивает мой):

Расширенное индексирование запускается, когда объект выделения obj является объектом без кортежей , ndarray (целочисленного типа данных или bool) или кортежем с по меньшей мере одним объектом последовательности или ndarray (типа данных integer или bool). Существует два типа расширенной индексации: integer и Boolean.

<Вырезано>

Также признайте, что x[[1,2,3]] вызовет расширенную индексацию, тогда как x[[1,2,slice(None)]] вызовет базовую нарезку .

Я знаю, почему x[(1, 2, slice(None))] запускает базовую нарезку. Но почему x[[1,2,slice(None)]] запускает базовое нарезку, когда [1,2,slice(None)] удовлетворяет условию последовательности без кортежа?


Что связано с примечанием, почему происходит следующее?

 >>> a = np.eye(4) >>> a[(1, 2)] # basic indexing, as expected 0.0 >>> a[(1, np.array(2))] # basic indexing, as expected 0.0 >>> a[[1, 2]] # advanced indexing, as expected array([[ 0., 1., 0., 0.], [ 0., 0., 1., 0.]]) >>> a[[1, np.array(2)]] # basic indexing!!?? 0.0 

  • В Tkinter как удалить фокус с виджета?
  • Как получить несколько подзадач в matplotlib?
  • Извлечь субтитры электронной почты из большого документа
  • Программа застревает при использовании subprocess.Popen () или subprocess.check_call ()
  • Что делает этот дескриптор безопасности плохим?
  • читать маркеры .wav-файла
  • gdb-python: анализируя структуру каждого поля и печатая их с правильным значением, если существует
  • Простой апплет панели Gnome в Python
  • 2 Solutions collect form web for “Расширенный нарезка при передаче списка вместо кортежа в numpy”

    Существует исключение из этого правила. Раздел документации Advanced Indexing не упоминает об этом, но выше, рядом с началом раздела Basic Slicing and Indexing вы увидите следующий текст:

    Чтобы оставаться обратно совместимым с обычным использованием в Numeric, базовая нарезка также инициируется, если объектом выбора является любая последовательность, отличная от ndarray (например, список), содержащая объекты среза , объект Ellipsis или объект newaxis, но не для целые массивы или другие встроенные последовательности.


    a[[1, np.array(2)]] не совсем инициирует базовое индексирование. Он запускает недокументированную часть логики обратной совместимости, как описано в комментарии в исходном коде:

      /* * Sequences < NPY_MAXDIMS with any slice objects * or newaxis, Ellipsis or other arrays or sequences * embedded, are considered equivalent to an indexing * tuple. (`a[[[1,2], [3,4]]] == a[[1,2], [3,4]]`) */ 

    np.array(2) внутри списка заставляет список обрабатываться так, как если бы он был кортежем, но результат, a[(1, np.array(2))] , по-прежнему является расширенной операцией индексирования. Он заканчивает применение 1 и 2 к отдельным осям, в отличие от a[[1, 2]] , и результат заканчивается похожим a[[1, 2]] a[1, 2] , но если вы попробуете его с 3D- a , он производит вместо просмотра.

    С помощью фиктивного класса я могу определить, как интерпретатор переводит [...] в вызовы __getitem__ .

     In [1073]: class Foo(): ...: def __getitem__(idx): ...: print(idx) In [1080]: Foo()[1,2,slice(None)] (1, 2, slice(None, None, None)) In [1081]: Foo()[(1,2,slice(None))] (1, 2, slice(None, None, None)) In [1082]: Foo()[[1,2,slice(None)]] [1, 2, slice(None, None, None)] 

    Таким образом, перенос нескольких терминов с помощью () не имеет значения – в обоих случаях он получает кортеж. И список передается как список.

    Таким образом, различие между кортежем и списком (или нет) должно быть закодировано в исходном коде numpy который компилируется. Поэтому я не могу это легко изучить.

    С 1d массивом

    индексирование со списком создает расширенные индексирование – выбор конкретных значений:

     In [1085]: arr[[1,2,3]] Out[1085]: array([ 0.73703368, 0. , 0. ]) 

    но заменяя одно из этих значений на кортеж или срез:

     In [1086]: arr[[1,2,(2,3)]] IndexError: too many indices for array In [1088]: arr[[1,2,slice(None)]] IndexError: too many indices for array 

    и список рассматривается как кортеж – он пытается сопоставить значения с размерами.

    Таким образом, на верхнем уровне список и кортеж обрабатываются одинаково – если список не может интерпретироваться как расширенный список индексирования.

    Также обратите внимание на то, какие списки отдельных позиций

     In [1089]: arr[[1]] Out[1089]: array([ 0.73703368]) In [1090]: arr[(1,)] Out[1090]: 0.73703367969998546 In [1091]: arr[1] Out[1091]: 0.73703367969998546 

    Некоторые функции, такие как np.apply_along/over_axis генерируют индекс как список или массив, а затем применяют его. Они работают со списком или массивом, потому что он изменен. Некоторые затем завертывают его в tuple перед использованием в качестве индекса; другие не беспокоились. Этот разброс меня беспокоил, но этот тестовый пример указывает на то, что такой кортеж, который часто обертывается, необязателен.

     In [1092]: idx=[1,2,slice(None)] In [1093]: np.ones((2,3,4))[idx] Out[1093]: array([ 1., 1., 1., 1.]) In [1094]: np.ones((2,3,4))[tuple(idx)] Out[1094]: array([ 1., 1., 1., 1.]) 

    Похоже, что кортеж кортежа по-прежнему необходим, если я создаю индекс как массив объектов:

     In [1096]: np.ones((2,3,4))[np.array(idx)] ... IndexError: arrays used as indices must be of integer (or boolean) type In [1097]: np.ones((2,3,4))[tuple(np.array(idx))] Out[1097]: array([ 1., 1., 1., 1.]) 

    ===================

    Комментарий от функции @Eric linked

      /* * Sequences < NPY_MAXDIMS with any slice objects * or newaxis, Ellipsis or other arrays or sequences * embedded, are considered equivalent to an indexing * tuple. (`a[[[1,2], [3,4]]] == a[[1,2], [3,4]]`) */ 

    ===================

    Эта функция обертывает массивы объектов и списки в кортеже для индексирования:

     def apply_along_axis(func1d, axis, arr, *args, **kwargs): .... ind = [0]*(nd-1) i = zeros(nd, 'O') .... res = func1d(arr[tuple(i.tolist())], *args, **kwargs) outarr[tuple(ind)] = res 
    Python - лучший язык программирования в мире.