Unexpected behaviour numpy array indexing [duplicate]

杀马特。学长 韩版系。学妹 提交于 2020-04-03 09:59:57

问题


The shape of a numpy array is changing when performing specific slicing in a somewhat unexpected manner

I have tried several ways of slicing the same array but slight differences lead to different outcomes in the shape of the array

import numpy as np
z = np.zeros((1,9,10,2))

# This makes sense
print(z[...,[1,0]].shape)
# (1, 9, 10, 2)
print(z[0,...].shape)
# (9, 10, 2)
print(z[0:1,...,[1,0]].shape)
# (1, 9, 10, 2)
print(z[0][...,[1,0]].shape)
# (9, 10, 2)

# This doesn't, I would expect (9, 10, 2) in both cases
print(z[0,:,:,[1,0]].shape)
# (2, 9, 10)
print(z[0,...,[1,0]].shape)
# (2, 9, 10)

In the last two examples I do not understand why the last axis is moved to the first position.

I am using Python 3.6.4 with numpy 1.15.1


回答1:


The reason why you might find the result in the two last cases unexpected, is because the indexing of the array is following the rules of advanced indexing, even though you're also indexing with slices.

For an extensive explanation behind this behaviour, you can check combining advanced and basic indexing. In these last cases in which you're getting unexpected resulting shapes. In the docs, you'll see that one of the mentioned scenarios in which we might obtain unexpected results is when:

  • The advanced indexes are separated by a slice, Ellipsis or newaxis. For example x[arr1, :, arr2].

In your case, although you're only using an integer for indexing along the first axis, it is broadcasted and both arrays are iterated as one. In this case the dimensions resulting from the advanced indexing operation come first in the result array, and the subspace dimensions after that.

The key here is to understand that as mentioned in the docs, it is like concatenating the indexing result for each advanced index element.

So in essence it is doing the same as:

z = np.random.random((1,9,10,2))
a = np.concatenate([z[0,:,:,[1]], z[0,:,:,[0]]], axis=0)
b = z[0,:,:,[1,0]]

np.allclose(a,b)
# True

But... why does this happen??

The reason behind this is that advanced indexing and basic indexing behave differently given that they serve different purposes. Lets go through an example to make this clear:

a = np.random.randint(1,10, (3,3,4))

print(a)
array([[[8, 2, 7, 2],
        [3, 1, 2, 4],
        [9, 8, 2, 2]],

       [[4, 2, 7, 4],
        [9, 6, 6, 7],
        [4, 2, 5, 1]],

       [[7, 4, 2, 3],
        [6, 9, 3, 6],
        [3, 3, 2, 6]]])

Now say we want to index a in order to obtain the two last columns from the first two 2d arrays. Well for this the way to go is with basic slicing:

a[:2,:,2:]

array([[[7, 2],
        [2, 4],
        [2, 2]],

       [[7, 4],
        [6, 7],
        [5, 1]]])

But now, what if I wanted to do the same, but instead of selecting the two last columns, I want the first and then the second from the two arrays respectively? How could I approach that? Well for that we have advanced indexing:

a[[0,1],:,[2,3]]

array([[7, 2, 2],
       [4, 7, 1]])

So as you can see both indexing methodologies are fundamentally different:

Integer array indexing allows selection of arbitrary items in the array based on their N-dimensional index. Each integer array represents a number of indexes into that dimension

When using several advanced indexes advanced indexes always are broadcast and iterated as one, where the obtained result has the shape:

result[i_1, ..., i_M] == x[ind_1[i_1, ..., i_M], ind_2[i_1, ..., i_M], ind_N[i_1, ..., i_M]]


So the resulting shapes will differ, even though the slices contain the same amount of axis elements as the array indexes. Reason being, that as mentioned, both indexing methodologies serve different purposes.

This however wouldn't happen if there was a single advanced index:

a[:2,:2,[2,3]]

array([[[7, 2],
        [2, 4],
        [2, 2]],

       [[7, 4],
        [6, 7],
        [5, 1]]])

Because there aren't any other advanced indices to broadcast with, and hence the indexing array is acting as a slice along the last axis.



来源:https://stackoverflow.com/questions/56299237/unexpected-behaviour-numpy-array-indexing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!