「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」
前言
继上一期 numpy 基本索引与切片中,numpy 借鉴了标准的Python x[obj] 语法进行索引。
根据 obj 对象类型不同,索引主要分为 基本索引和高级索引。
在单元素索引中,对于一维数组来说索引返回的是原始数组的副本。对于N维数组,当少于数组维数的索引对象,则返回是原始数组的视图。
基本索引中,我们可以使用 start:stop:step 来进行切片操作,基本操作逻辑与Python list、字符串等支出正索引和负索引,当::时,是取所有数组元素值。
同时在进行切片过程中,要确保设置的值的大小与原数组形状保持一致。
但是,start:stop:step 这种切片方式不适合高级索引。
相信大家,一定充满对高级索引的好奇,哪接下来我们开始学习高级索引相关概念,Let's go~~
1. 高级索引
-
什么是高级索引?
numpy 模块索引是沿用 Python 标准的索引方式 x[obj]。
-
触发高级索引条件
- 当 obj 是非元组序列
- ndarray的数据元素类型为布尔类型
- 数据类型为整数或布尔值的元组
高级索引总是返回的数据的副本,与基本切片返回视图相反。
-
2. 整数数组索引
2.1 什么是整数数组索引?
整数数组索引是以元素是整数类型的ndarray对象进行索引查询多个任意数据元素。
与基本索引和切片一样,索引数组支持正索引和负索引。
-
整数数组索引为ndarray对象
(an ndarray(of data type integer or bool))
>>> import numpy as np >>> intarr = np.arange(12) >>> intarr array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) >>> intarr[np.array([3,5,7,9])] array([3, 5, 7, 9]) >>>如果索引中,对象不是ndarray,则系统会报TypeError错误
>>> intarr([3,5,7,9]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'numpy.ndarray' object is not callable -
整数数组索引为list对象
a non-tuple sequence object
>>> intarr[[3,5,7,9]] array([3, 5, 7, 9]) -
整数数组索引为包含序列的tuple对象
>>> intarr[([3,5,7,9])] array([3, 5, 7, 9])
索引值为负数时,其工作原理与切片一样,从数组未位开始进行查找
>>> intarr
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
>>> intarr[([1,2,-3,-1])]
array([ 1, 2, 9, 11])
>>>
当索引值超时范围是,系统会报IndexError
>>> intarr[([13])]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: index 13 is out of bounds for axis 0 with size 12
>>>
2.2 多维数组的整数数组索引
-
当多维数组与索引维度一样多时,numpy 内部会进行广播和迭代,如下栗子。
>>> intarr2 = np.array([[2,3],[4,5],[8,9]]) >>> intarr2 array([[2, 3], [4, 5], [8, 9]]) >>> intarr2[[1,-1]] array([[4, 5], [8, 9]])
同理,当索引数组值大于原数组时,会触发 numpy indexError
>>> intarr2[[3,1]]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: index 3 is out of bounds for axis 0 with size 3
>>>
2.3 多维数组的整数数组应用
-
多维数组整数索引常规操作
官方给出高级索引的迭代公式
result[i_1, ..., i_M] == x[ind_1[i_1, ..., i_M], ind_2[i_1, ..., i_M], ..., ind_N[i_1, ..., i_M]]当索引数组与原数组的形状一致时,在每个维度都在合法范围内,结果返回与索引数组的shape一样。 比如,我们下面的案例,intarr3[np.array([1,2,3]),np.array([1,3,2])] = intarr3[1,1] intarr3[2,3] intarr3[3,2]
>>> intarr3 = np.arange(20).reshape(5,4) >>> intarr3 array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [12, 13, 4,1 15], [16, 17, 18, 19]]) >>> intarr3[np.array([1,2,3]),np.array([1,3,2])] array([ 5, 11, 14]) >>>
我们之前在了解到 numpy 广播规则时,触发广播后,输出的结果shape与原数组shape保持一致,否则的话,系统会报shape不一致的异常
>>> intarr3[np.array([1,2,3]),np.array([1,3])]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (3,) (2,)
>>>
-
numpy 广播机制允许与其他索引重叠
如下案例,我们可以看到intarr3[np.array([1,2,3]),1]= intarr3[1,1]intarr3[2,1]intarr3[3,1]
>>> intarr3 array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [12, 13, 14, 15], [16, 17, 18, 19]]) >>> intarr3[np.array([1,2,3]),1] array([ 5, 9, 13]) >>>
3. 布尔索引
Numpy 模块中,当索引对象为布尔类型时,也会触发高级索引。
布尔索引是布尔运算来获取指定的元素数据
布尔索引最常见的应用是过滤所需要的的元素值
>>> intarr3
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19]])
>>> intarr3[[intarr3>5]]
array([ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
>>>
4. 花式索引
花式索引是整数数组索引的拓展,专门针对多个索引数组时,调用np.ix_来实现广播。
>>> intarr3
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19]])
>>> intarr3[[intarr3>5]]
array([ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
>>> intarr3[[3,4,4,1]]
array([[12, 13, 14, 15],
[16, 17, 18, 19],
[16, 17, 18, 19],
[ 4, 5, 6, 7]])
>>> intarr3[[-3,-1,-1,-1]]
array([[ 8, 9, 10, 11],
[16, 17, 18, 19],
[16, 17, 18, 19],
[16, 17, 18, 19]])
类似切片的功能,高级索引可以调用np.ix_方法实现广播机制
>>> intarr3[np.ix_([-3,-1,-1,-1],[0,1,2,3])]
array([[ 8, 9, 10, 11],
[16, 17, 18, 19],
[16, 17, 18, 19],
[16, 17, 18, 19]])
>>>
总结
本期,对numpy 模块中关于高级索引两种类型整数数组索引和布尔索引相关操作,进行学习。
相对于基本索引来说,高级索引可以帮助我们实现更多的功能,如迭代和广播
以上是本期内容,欢迎大佬们点赞评论,下期见~