Search code examples
numpynumpy-ndarrayarray-broadcastingnumpy-slicing

numpy multidimensional indexing :use np array and list give different results


why b1 b2 give different result, but b0 ,b1,b3 give the same. and get an
"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."

a = np.array([[6, 7], [8, 9]])
print(a.shape)
print(a)
print()

b0 = a[[0, 0]]
print('b0')
print(b0.shape)
print(b0)
print()

b1 = a[[[0, 0]]]
print('b1')
print(b1.shape)
print(b1)
print()

b2 = a[np.array([[0, 0]])]
print('b2')
print(b2.shape)
print(b2)
print()

b3= a[np.array([0, 0])]
print('b3')
print(b3.shape)
print(b3)

(2, 2) [[6 7] [8 9]]

b0 (2, 2) [[6 7] [6 7]]

b1 (2, 2) [[6 7] [6 7]]

b2 (1, 2, 2) [[[6 7] [6 7]]]

b3 (2, 2) [[6 7] [6 7]]


Solution

  • As a matter of history

    b1 = a[[[0, 0]]]
    

    was/is evaluated as

    b1 = a[([0, 0],)]
    b1 = a[[0, 0]]
    

    The warning is telling us that this anomaly is being corrected.

    Indexing like a[i,j] is really a[(i,j)], passing a tuple to the getitem method. Due to mergers of various packages way in past, under some circumstances a list was interpreted in the same way. You found one.

    The futurewarning is telling us that the cleanest, clearest way of doing advanced indexing is with tuples and arrays. There was, and to an extent still is, an ambiguity when using lists.

    This is described in the 1.15.0 release notes deprecations,

    Multidimensional indexing with anything but a tuple is deprecated. This means that 
    the index list in ind = [slice(None), 0]; arr[ind] should be changed to a tuple, 
    e.g., ind = [slice(None), 0]; arr[tuple(ind)] or arr[(slice(None), 0)]. 
    That change is necessary to avoid ambiguity in expressions such as 
    arr[[[0, 1], [0, 1]]],  interpreted as arr[array([0, 1]), array([0, 1])], 
    that will be interpreted as arr[array([[0, 1], [0, 1]])] in the future.
    

    So in the future b1 will behave like b2, but for now it is like b0.