Numpy数组索引/切片 多维度索引

在处理低维度Numpy数组时,索引或者切片操作往往可以一眼看出结果,但是随着数组维度的增加,以及索引数组维度的增加或者切片的混合,往往就无法一眼看出结果,甚至自己都推不出结果,本文将带你一一解决。

1.Numpy中一些简单的等式

arr[0][1] == arr[0, 1]

arr[[0, 1]] == [arr[0], arr[1]]

2.低维度数组低维度索引与切片

arr = np.arange(10) # [0 1 2 3 4 5 6 7 8 9]

# Example_1
t1 = arr[0] # 0

# Example_2
t2 = arr[[1, 3, 5]] # [1, 3, 5]

# Example_3
t3 = arr[1:6] # [1, 2, 3, 4, 5]

# Example_4
t4 = arr[1:6:2] # [1, 3, 5]

3.低纬度数组高维度索引

arr = np.arange(10:0:-1) # [10 9 8 7 6 5 4 3 2 1]

# Example_1
t1 = arr[np.array([[1, 2, 3], [4, 5, 6]])] # [[9 8 7], [6 5 4]]

# Example_2
t2 = arr[np.array([[[[[1, 2], [3, 4]]]]])] # [[[[[9, 8], [7, 6]]]]]

推导:

由1中的第二个基本等式我们可以知道,arr[[0, 1]] = [arr[0], arr[1]]
那么,如果我们将0, 1换成数组,该等式应该也是成立的,所以arr[np.array([[1, 2, 3], [4, 5, 6]])]
应该也可以进行"降维索引"变为:[arr[[1, 2, 3]], a[[4, 5, 6]]]
同理我们再次使用变换:[[arr[1], arr[2], arr[3]], [arr[4], arr[5], arr[6]]]
将arr[1], arr[2]等带入得到结果:[[9, 8, 7], [6, 5, 4]]
Example_2也是如此可以推出

我们可以总结得到一个规律:A[arr] == [ A[arr[0]], A[arr[1]], ..., A[arr[n]] ]

通过以上这个规律我们可以推导出任意维度数组的任意维度索引的结果

4.高维度数组高维度索引

对于低维度索引就不做过多阐述

arr = np.arange(24).reshape(3, 2, 4)
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]],

       [[16, 17, 18, 19],
        [20, 21, 22, 23]]])

# Example_1
t1 = arr[np.array([[0, 1], [1, 0]])]
[[[[ 0  1  2  3]
   [ 4  5  6  7]]

  [[ 8  9 10 11]
   [12 13 14 15]]]


 [[[ 8  9 10 11]
   [12 13 14 15]]

  [[ 0  1  2  3]
   [ 4  5  6  7]]]]

通过以上的例子我们可以总结出,针对高维度索引数组快速得到结果的方法:

将索引数组中的数字i换成arr[i]即可,看如下示例:

arr = np.arange(24).reshape(3, 2, 4)

t = arr[np.array([[[[[[[[[[[[[1, 2], [2, 1]]]]]]]]]]]]])]
[[[[[[[[[[[[[arr[1], arr[2]], [arr[2], arr[1]]]]]]]]]]]]]] 
# arr的第一层索引可以很快获得,所以我们可以快速得到结果

5.多个索引数组

索引的中括号内有多个数组的时候,与上面的情况就有所不同了

arr = np.arange(24).reshape(3, 2, 4)
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]],

       [[16, 17, 18, 19],
        [20, 21, 22, 23]]])

# Example_1
t1 = arr[[2, 1], [0, 1]] # [[16, 17, 18, 19], [12, 13, 14, 15]]

# Example_2
t2 = arr[[2, 1], [0, 1], [2, 3]] # [18, 15]

# Example_3
t3 = arr[[0, 1, 2], [0, 1, 0], [3, 1, 2]] # [3, 13, 18]

其实在Example_1中,就是把arr[2, 0]arr[1, 1] 放在了一个数组内得到结果

Example_2中就是把arr[2, 0, 2]arr[1, 1, 3] 放在一个数组内得到结果

Example_3则是arr[0, 1, 3]arr[1, 1, 1]arr[2, 0, 2] 放到一个数组内

所以不难总结出规律: a[arr1, arr2,...arrn] = [a[arr1[0], arr2[0], ...arrn[0]], a[arr1[1], arr2[1], ...arrn[1]], ..., arr1[m], arr2[m], arrn[m]] ]

6.布尔索引

布尔索引与数组索引的操作完全不同,只需谨记一句:布尔索引的结果是将布尔索引中为True的元素对应的原数组中的元素都放到一个数组中即为结果。可能有点绕,看下面例子:

arr = np.arange(24).reshape((3, 2, 4))
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]],

       [[16, 17, 18, 19],
        [20, 21, 22, 23]]])

# Example_1
b_arr = np.array([True, False, True])
print(arr[b_arr])
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[16, 17, 18, 19],
        [20, 21, 22, 23]]])

# Example_2
b_arr = np.array([[True, False], [False, True], [False, False]])
print(arr[b_arr])
[[ 0  1  2  3]
 [12 13 14 15]]

# Example_3
b_arr = np.array([
    [[True, False, False, True],
     [False, False, True, False]],
    [[False, True, True, False],
     [True, False, True, False]],
    [[False, False, False, False],
     [True, True, True, True]]])
print(arr[b_arr])
[ 0  3  6  9 10 12 14 20 21 22 23]

在布尔数组索引中,索引的布尔数组的大小是有一定限制的,如上述例子中arr 数组的大小为3x2x4 那么布尔数组的大小只能为:(3,) 或者(3, 2) 或者(3, 2, 4),这样才能正确对应原数组中不同维度的元素。

讲解:

在Example_1中,布尔数组为[True, False, True]
这个布尔数组中的三个元素分别对应着原数组中的arr[0], arr[1], arr[2]
而True位置对应的就是arr[0]和arr[2],那么结果就是把二者放在一个数组里即是结果
[arr[0], arr[2]] = [
					[[ 0,  1,  2,  3],[ 4,  5,  6,  7]],
					[[16, 17, 18, 19],[20, 21, 22, 23]]
					]
同理在Example_2中,布尔数组为[[True, False], [False, True], [False, False]]
里面有三个子数组,对应原数组的三个直接子元素,也就是arr[0], arr[1], arr[2]
而第一个子数组[True, False]对应的就是arr[0]中的两个元素,也就是arr[0][0]和arr[0][1]
同理第二个数组[False, True]对应的就是arr[1]中的两个元素,也就是arr[1][0]和arr[1][1]
同理第二个数组[False, False]对应的就是arr[2]中的两个元素,也就是arr[2][0]和arr[2][1]
所以最终结果就是把True对应的元素放在一个数组里,即[arr[0][0], arr[1][1]]
即[[ 0  1  2  3], [12 13 14 15]]
Example_3也是同样的道理
posted @ 2022-08-09 15:11  凡璞  阅读(196)  评论(0编辑  收藏  举报
1 2
3 4
5 6