lianwei82cn
lianwei82cn

Reputation: 31

is it a bug of numpy advanced indexing?

A weird result occured when dealing with numpy advanced indexing. Is it a bug or numpy's constraint?

>>> a = np.arange(9).reshape((3,3,))
>>> a[0,1]         # OK
1
>>> a[[0,1]]       # OK
array([[0, 1, 2],
       [3, 4, 5]])
>>> a[[[0,1]]]     # ? (the result is 2-dim instead of 3-dim. just as same as a[[0,1]]. )
array([[0, 1, 2],
       [3, 4, 5]])
>>> a[[[[0,1]]]]   # ?
array([[[0, 1, 2],
        [3, 4, 5]]])

I also tried the following, It's OK.

>>> a[[[0,1]],]   # OK
array([[[0, 1, 2],
        [3, 4, 5]]])

Upvotes: 2

Views: 73

Answers (2)

NeoZoom.lua
NeoZoom.lua

Reputation: 2891

At case a[[[0,1]]] you're passing a 2d-list into the index of a np.array, which means it's equivalent to a[tuple([[0,1]])], which get further simplified into a[[0,1],]. This triggers advanced indexing, so the result is of shape (2,3) since you're literally stacking the 0-th and 1-th rows:

array([  [0, 1, 2],     # 0-th row
         [3, 4, 5]  ])  # 1-th row

which has shape (2, 3).

On the other hand, a[[[[0,1]]]] you're passing a 3d-list [...]. And instead the result is equivalent to a[([[0,1]], )], i.e. the first component of the tuple is 2d. By advanced indexing(again), you're just "wrapping an extra layer of [] to the result" or "pretending the shape of the result with a 1,". This gives:

array([
    [                # this is what you did: the extra layer
      [0, 1, 2],     # 0-th row
      [3, 4, 5]      # 1-th row
    ]
])

which has shape (1, 2, 3).

Upvotes: 0

hpaulj
hpaulj

Reputation: 231325

In a current version, 1.18:

In [13]: a[[[0,1]]]                                                                                    
/usr/local/bin/ipython3:1: FutureWarning: Using a non-tuple sequence 
for multidimensional indexing is deprecated; use `arr[tuple(seq)]` 
instead of `arr[seq]`. In the future this will be interpreted as an 
array index, `arr[np.array(seq)]`, which will result either in an 
error or a different result.
  #!/usr/bin/python3
Out[13]: 
array([[0, 1, 2],
       [3, 4, 5]])
In [14]: a[np.array([[0,1]])]                                                                          
Out[14]: 
array([[[0, 1, 2],
        [3, 4, 5]]])
In [15]: _.shape                                                                                       
Out[15]: (1, 2, 3)

In other words, previous versions interpreted [13] as

In [16]: a[([0,1],)]                                                                                   
Out[16]: 
array([[0, 1, 2],
       [3, 4, 5]])
In [17]: _.shape                                                                                       
Out[17]: (2, 3)

In [18]: a[([[0,1]],)].shape                                                                           
Out[18]: (1, 2, 3)

Numpy has been slowly cleaning up indexing edge cases, which were largely the result of merging several different numeric packages years ago.

===

Your comment case in readable form:

In [19]: a[[0,1],[0,1]]                                                                                
Out[19]: array([0, 4])
In [20]: a[[[0,1],[0,1]]]                                                                              
/usr/local/bin/ipython3:1: FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; use `arr[tuple(seq)]` instead of `arr[seq]`. In the future this will be interpreted as an array index, `arr[np.array(seq)]`, which will result either in an error or a different result.
  #!/usr/bin/python3
Out[20]: array([0, 4])
In [21]: a[([0,1],[0,1])]                                                                              
Out[21]: array([0, 4])
In [22]: a[[[[0,1],[0,1]]]]                                                                            
/usr/local/bin/ipython3:1: FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; use `arr[tuple(seq)]` instead of `arr[seq]`. In the future this will be interpreted as an array index, `arr[np.array(seq)]`, which will result either in an error or a different result.
  #!/usr/bin/python3
Out[22]: 
array([[[0, 1, 2],
        [3, 4, 5]],

       [[0, 1, 2],
        [3, 4, 5]]])
In [23]: a[np.array([[[0,1],[0,1]]])]                                                                  
Out[23]: 
array([[[[0, 1, 2],
         [3, 4, 5]],

        [[0, 1, 2],
         [3, 4, 5]]]])

Upvotes: 3

Related Questions