数组的索引与切片
数组的索引
类似 Python 的列表,numpy 中的数组也可以用中括号指定获取索引值位置的元素。索引值同样从零开始计数,且可以使用负数索引获取末尾元素:
不同与 Python 的嵌套列表,可以用逗号分隔的索引元组获取多维数组的某一元素,而不需要多次索引:
索引元组是多次切片的一个便捷替代,因此前面的值代表的是外层数组的索引。
可以用以上的索引方式为数组内某个位置的元素分配一个新值:
注意,numpy 的数组是固定类型的,当将一个不同类型的元素插入数组时,它会被隐式地截短转换:
数组的切片
numpy 的数组也支持切片语法,语法和 Python 对序列的切片一致。如果 arr
是一个数组,可以用以下语法对 arr
切片:
对一维数组的切片很简单,与 Python 切片语法一致。例如以下几个简单示例:
多维数组的切片也采用类似索引的方法处理:可以用逗号分隔的切片对象来逐维切片,例如:
该切片的意思是先在第二个维度(列方向)取前 2 项元素,再在第一个维度(行方向)取前三项元素。下面再给出一个更复杂的示例:
一种常见的需求是获取多维数组的特定行和列。这种情况下,可以用索引与切片组合起来实现该功能,用单个冒号“ :
”表示空切片(即不做切片,获取该维度的所有元素):
意思是不对第二个维度做切片(保留所有行),然后获取每行的首个元素。再如:
在更高维的数组切片中,还可以使用省略号来表示多个连续的空切片,例如:
为了不发生歧义,一个切片中最多只能使用一个省略号。
最后关于数组切片需要注意的是,切片返回的也是数组的视图,因此在切片中修改元素也会影响原数组。如果确实需要得到一个副本子数组的话,可以对切片对象使用 .copy()
方法得到副本。
切片与数组升维
切片还可用于给数组增加维度。一种常见的需求是将一个数组变成二维数组的行或列,此时可以在数组切片中使用 np.newaxis
变量给数组添加新维度,具体操作为:
以上操作在 np.newaxis
对应的位置加上了一个维度,使数组的形状变成了 (-1, 1)
,形成二维数组(列向量)。
可以结合以下升维再切片降维的过程理解,两个切片互为逆过程:
np.newaxis
实际上是 None
的别名。该过程虽然是升维,但得到的也是数组的视图。
高级索引机制
数组索引
接下来简单介绍另外一种索引方式数组索引,也称作花哨的索引(fancy indexing)。花哨的索引和前面那些简单的索引非常类似,但是传递的是索引数组,而不是单个标量。这种强大的索引能够快速获得并修改复杂的数组值的子数据集。
如果在索引中传递单个列表或数组,它包括的元素会被当做索引值,可以获取若干元素构成的数组(视图):
数组索引得到的数组形状与索引的形状一致,而不是与原数组的形状一致:
这种索引方式也适用于多维数组,不过多维数组下的数组索引是这样工作的:如果向索引内传入多个数组,那么每个数组分别确定每个维度的索引。例如:
以上两个数组结合确定了三个位置:[1, 0] [2, 1] 和 [2, 3] 。
可以将普通索引、切片和数组索引组合使用,使数组在某些维度做普通索引,某些维度做切片,某些维度用数组索引。例如,索引:
取第二行的数组中除最后一个元素外的所有元素,但不改变数组间的嵌套关系。再如:
取第一行及往后的第一个和最后一个元素,但不改变数组间的嵌套关系。
用数组索引修改值
切片和数组索引可以用于获取部分元素,并且返回的是数组视图。如果对视图内的元素赋值,可以批量修改数组的一部分数据,例如:
可以做任意的赋值操作,例如:
数组索引有一种特殊情况,那就是对同一个位置做了多次索引,导致重复获取该位置的值。如果对一个位置做重复的赋值,会导致前面的赋值被覆盖:
因为该操作对最后一个位置的元素赋值了两次。覆盖的本质是只有最后一次对元素的操作才有效,因此对同一个元素的多次复合运算赋值不会累计起效:
本节对数组的索引机制暂时到这边结束。下一节将介绍通用函数和数组的广播机制,可以结合数组索引做一些更复杂的操作。