Advanced slicing when passing a list instead of a tuple in numpy

The docs say (emphasizes mine):

Extended indexing is triggered when the selection object, obj, is a sequence object without a binding , ndarray (data type integer or bool), or a tuple with at least one sequence object or ndarray (data type integer or bool). There are two types of advanced indexing: integer and Boolean.

<notch>

Also admit that it x[[1,2,3]]will cause advanced indexing , while it x[[1,2,slice(None)]]will trigger the basic slicing .

I know why it x[(1, 2, slice(None))]starts basic slicing. But why does it x[[1,2,slice(None)]]start basic slicing when it [1,2,slice(None)]matches the condition of a sequence that is not in the tuple?


Depending on the note, why the following happens:

>>> 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
+3
source share
2 answers

There is an exception to this rule. The Advanced Indexing documentation section does not mention this, but above, at the beginning of the Basic Slicing and Indexing section , you will see the following text:

, 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], 3D a, .

+6

, [...] __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

    /*
     * 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
+1

Source: https://habr.com/ru/post/1664317/


All Articles