导入 NumPy 库:
In [1]:
import numpy as np #导入 NumPy 库 np.__version__ #打印numpy版本
Out[1]:
'1.24.2'
细心的读者可以发现,前面的切片和索引操作只能索引出有规律的元素数据,比如同轴向,若要索引如下元素则无法实现,下面就介绍数组的高级索引,可以实现对任意元素的索引。 
2.2.3: 数组高级索引 -花式索引
花式索引是指NumPy使用整型数组作为索引。
整型数组作为索引可以获取数组中任意元素。整型数组表示方式是每个维度都可以是该维度的一组下标值,可以用NumPy数组,元组或列表形式表示。若某个维度缺省索引则表示该维度索引该维度的所有下标。
花式索引其实就是索引的扩展,前面的索引操作每个维度都只有一个下标,而花式索引时维度是采用一组下标进行索引。需要注意的是,花式索引有两种情况:
- 每个维度的整数数组索引的下标数目要相同,索引时是对应位置的各维度的下标组成下标对进行索引,索引得到一维数组。
- 每个维度的整数数组索引的下标数目不相同时,只允许两种情况,要么有的维度无索引,表示该维度索引全部元素,要么有的维度只有一个下标索引。否则报错。
其意义是根据采用整型数组作为目标数组的某个轴的下标值进行索引。当我们想以特定的顺序来选取子集的时候,只需传入一个用于指定顺序的整数列表或ndarray即可。
下面通过实例来展示花式索引过程:
In [2]:
arr2_3_1 = np.arange(1,16) arr2_3_1
Out[2]:
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
In [3]:
arr2_3_1[5]
Out[3]:
6
通过列表或元组进行对arr2_3_1花式索引,可以索引出对应下标位置的元素,注意:使用元组时需要在元组后有个逗号。否则报错
In [4]:
arr2_3_1[[4,6,2]]
Out[4]:
array([5, 7, 3])
In [5]:
arr2_3_1[(4,6,2),] #使用元组时需要在元组后有个逗号
Out[5]:
array([5, 7, 3])
一维数组的花式索引结果是对应位置的元素组成新的一维数组。
2、多维数组花式索引
In [6]:
arr2_3_2 = np.arange(1,16).reshape(3,5) arr2_3_2
Out[6]:
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]])
各维度以元组方式进行花式索引:
In [7]:
arr2_3_2[(0,1,2),(4,2,3)]
Out[7]:
array([ 5, 8, 14])
也可以是列表形式:
In [8]:
arr2_3_2[[0,1,2],[4,2,3]]
Out[8]:
array([ 5, 8, 14])
图示如下,两个维度都取三个下标进行索引,相当于从每个维度的整型数组对应位置取出下标组成下标对:(0,4),(1,2),(2,3)进行索引:arr2_3_2[0,4], arr2_3_2[1,2], arr2_3_2[2,3],索引结果形成一个新的一维数组。

In [9]:
arr2_3_2[0,4]
Out[9]:
5
In [10]:
arr2_3_2[1,2]
Out[10]:
8
In [11]:
arr2_3_2[2,3]
Out[11]:
14
某个维度只有一个下标索引时:
In [12]:
arr2_3_2[(0,1,2),(4)]
Out[12]:
array([ 5, 10, 15])
这时NumPy数组会将下标4进行广播(广播机制后面会讲),形成花式索引arr2_3_2[(0,1,2),(4,4,4)] 形式,也就是索引arr2_3_2[0,4],arr2_3_2[1,4],arr2_3_2[2,4]。
In [13]:
arr2_3_2[(0,1,2),(4,4,4)]
Out[13]:
array([ 5, 10, 15])
某个维度缺省索引下标时:
In [14]:
arr2_3_2[(0,2),]
Out[14]:
array([[ 1, 2, 3, 4, 5],
[11, 12, 13, 14, 15]])
上述索引的结果是第二个维度取全部元素,相当于切片操作中只有冒号:,后面维度的切片若只有冒号:可以省略,而前面的不可以省略。
In [15]:
arr2_3_2[(0,2),:]
Out[15]:
array([[ 1, 2, 3, 4, 5],
[11, 12, 13, 14, 15]])
In [16]:
arr2_3_2[:,(0,2)] #轴0取全部即三行,轴1取第0列和第2列
Out[16]:
array([[ 1, 3],
[ 6, 8],
[11, 13]])
再举个三维数组的例子:
In [17]:
arr2_3_3 = np.arange(1,49).reshape(3,4,4) arr2_3_3
Out[17]:
array([[[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[13, 14, 15, 16]],
[[17, 18, 19, 20],
[21, 22, 23, 24],
[25, 26, 27, 28],
[29, 30, 31, 32]],
[[33, 34, 35, 36],
[37, 38, 39, 40],
[41, 42, 43, 44],
[45, 46, 47, 48]]])
In [18]:
arr2_3_3[[0,1,2],[3,1,2],[1,2,3]]
Out[18]:
array([14, 23, 44])
每个维度索引下标数相同,组成下标对(0,3,1),(1,1,2),(2,2,3),索引:arr2_3_3[0,3,1],arr2_3_3[1,1,2],arr2_3_3[2,2,3]
每个维度索引下标不相同时,对只有一个下标的整数数组索引的维度进行广播,对缺省维度进行切片所有元素
In [19]:
arr2_3_3[[0,1,2],[3],[1,2,3]] #相当于arr2_3_3[[0,1,2],[3,3,3],[1,2,3]]
Out[19]:
array([14, 31, 48])
In [20]:
arr2_3_3[[0,1],[3],[1]] #相当于arr2_3_3[[0,1],[3,3],[1,1]]
Out[20]:
array([14, 30])
In [21]:
arr2_3_3[[0,1],[3]] #相当于arr2_3_3[[0,1],[3,3],:]
Out[21]:
array([[13, 14, 15, 16],
[29, 30, 31, 32]])
In [22]:
arr2_3_3[[0,1],[3,3],:]
Out[22]:
array([[13, 14, 15, 16],
[29, 30, 31, 32]])
In [23]:
arr2_3_3[[0,1]] #相当于arr2_3_3[0,1],:,:]
Out[23]:
array([[[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[13, 14, 15, 16]],
[[17, 18, 19, 20],
[21, 22, 23, 24],
[25, 26, 27, 28],
[29, 30, 31, 32]]])
In [24]:
arr2_3_3[1:,(3,-2)] #相当于arr2_3_3[1:,(3,-2),:]
Out[24]:
array([[[29, 30, 31, 32],
[25, 26, 27, 28]],
[[45, 46, 47, 48],
[41, 42, 43, 44]]])
混合索引:切片+整数数组索引,索引轴0的第1、2组元素,在此基础上,再索引轴1的第3组和倒数第二组元素,用负数索引将会从末尾开始。
2.2.4: 数组高级索引-NumPy 布尔索引
- 布尔索引
通过布尔运算(如:比较运算符)来获取符合指定条件的元素的数组。
除了采用整型数组作为索引外,还可以采用布尔类型的数组(简称布尔数组)作为轴向索引,布尔值为True表示该轴向对应该布尔值位置的下标所对应元素被索引,为False则表示该轴向对应的该布尔值位置的下标所对应元素不被索引。
通过布尔数组的逻辑运算作为索引,以此过滤出布尔数组中值为True的对应数据。
需要注意,布尔型数组的长度必须与该轴向长度一致。
以二维数组arr2_3_3为例,arr2_3_3为3行5列:
In [25]:
arr2_3_2
Out[25]:
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]])
创建一个布尔类型的NumPy数组,0表示False,非0(一般用1)表示True
In [26]:
mask0 = np.array([1,0,1],dtype = np.bool_) mask0
Out[26]:
array([ True, False, True])
In [27]:
#mask是一个布尔数组 arr2_3_2[mask0,2]
Out[27]:
array([ 3, 13])
将布尔数组mask0作为行索引,True表示索引,False表示不索引,故索引第0行和第2行。
2为列索引,故索引第0、2行中第2列的元素。
拆解分析:
In [28]:
arr2_3_2[mask0]
Out[28]:
array([[ 1, 2, 3, 4, 5],
[11, 12, 13, 14, 15]])
即arr2_3_2[[ True, False, True]],索引出第0行和第2行。在此基础上再索引出第2列元素:
In [29]:
arr2_3_2[mask0][:,2]
Out[29]:
array([ 3, 13])
同样,与花式索引要求每个维度的整型数组索引的下标数目要相同类似,对多维数组而言,若各维度都采用布尔数组进行索引,需要满足各维度布尔值为True的数目相同。
如对arr2_3_2的轴1也采用布尔数组进行索引,分别创建mask1和mask2如下:
In [30]:
mask1 = np.array([1,0,0,1,0],dtype = np.bool_) mask1
Out[30]:
array([ True, False, False, True, False])
In [31]:
mask2 = np.array([1,0,0,1,1],dtype = np.bool_) mask2
Out[31]:
array([ True, False, False, True, True])
mask1有两个元素为True,表示索引出第0和第3列。mask2有三个元素为True,表示索引出第0、第3和第4列。
In [32]:
arr2_3_2
Out[32]:
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]])
In [33]:
arr2_3_2[:,mask1]
Out[33]:
array([[ 1, 4],
[ 6, 9],
[11, 14]])
In [34]:
arr2_3_2[:,mask2]
Out[34]:
array([[ 1, 4, 5],
[ 6, 9, 10],
[11, 14, 15]])
只有一个维度采用布尔数组索引都没有问题,但是对arr2_3_2两个维度都进行布尔数组索引:
In [35]:
mask0
Out[35]:
array([ True, False, True])
In [36]:
arr2_3_2[mask0,mask1]
Out[36]:
array([ 1, 14])
In [37]:
arr2_3_2[mask0,mask2]
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) Cell In[37], line 1 ----> 1 arr2_3_2[mask0,mask2] IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (2,) (3,)
可以发现,arr2_3_2[mask0,mask2]报错,原因就是各维度同时采用布尔数组索引的话,是各维度布尔数组索引中元素为True的下标按顺序对应组成下标对进行索引,这时就要求各维度的索引下标数目要相同。类似前面:arr2_3_2[(0,1,2),(4,2,3)]。 现在mask有两个True,mask2三个True故无法组成这种花式索引。
arr2_3_2[mask0,mask1]索引是布尔数组mask0和mask1中为True的下标依次两个组成下标对:(0,0),(2,3),也就是索引arr2_3_2[0,0],arr2_3_2[2,3]
(2,3)下标对表示布尔数组mask0的第一个True下标为2,布尔数组mask1的第一个True下标为3
也可以通过逻辑运算生成布尔数组进行索引:
In [38]:
arr2_3_5 = np.arange(0,12).reshape(4,3) arr2_3_5
Out[38]:
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
In [39]:
arr2_3_5 > 6
Out[39]:
array([[False, False, False],
[False, False, False],
[False, True, True],
[ True, True, True]])
In [40]:
arr2_3_5[arr2_3_5 > 6]
Out[40]:
array([ 7, 8, 9, 10, 11])
-
练习:布尔索引使用实例
创建一个color的一维数组如下:
In [41]:
color = np.array(["red","blue","green","blue","red","blue"]) color
Out[41]:
array(['red', 'blue', 'green', 'blue', 'red', 'blue'], dtype='<U5')
用numpy.random中的randn函数生成一个6 * 7数组data,用numpy.around保留data数组2位小数
In [ ]:
1.对color和字符串“blue”的比较运算将会产生一个布尔型数组:
In [ ]:
2.将这个布尔型数组用于data数组行索引:
In [ ]:
索引到哪几行?答:
3.将布尔型数组跟切片混合使用:将步骤1中这个布尔型数组用于data数组行索引,列切片为1:5
In [ ]:
4.多种条件组合(&,|等)
创建color等于bule或green的布尔类型数组,并作用于data数组的行索引:
In [ ]:
5.如何将data数组中的所有负值都设置为0:
In [ ]:
这篇博客详细介绍了NumPy数组的高级索引,包括花式索引和布尔索引。通过实例展示了如何使用整型数组进行花式索引,获取数组中任意位置的元素,以及如何利用布尔数组过滤出符合条件的元素。博客内容涵盖了不同维度数组的索引规则,以及混合使用切片和整型数组索引的方法。
483






