Numpy索引与切片操作
单元素索引
一维数据的单元素索引是最简单的一种索引方式,与Python列表的操作完全一致。
>>> x = np.arange(10)
>>> x
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> x[2]
2
二维以及多维数据的单元素索引与Python的列表操作并不完全一致。
在Numpy中提供了两种对多维数据进行单元素索引的方法,这里以二维数据为例。
>>> y = np.arange(12).reshape(3, 4)
>>> y
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
### 第一种索引方式
>>> y[1][2]
6
### 第二种索引方式
>>> y[1,2]
6
y[1] [2]和y[1, 2]都能对特定位置中的元素进行访问,前者是Python列表和Numpy都支持的索引方式,后者只适用于Numpy。
第二种索引方式的效率高于第一种索引方式,原因在于第一种方法会在第一个方括号时创建一个临时数组来对第二个方括号进行索引。
按行列索引
如果一个多维数组在索引时,索引数量少于其维度,那么会得到一个子维的数组。
>>> y
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> y[0]
array([0, 1, 2, 3])
冒号和省略号语法用于完整的选择出剩余未指定维度的数据。
array([0, 1, 2, 3])
### 获取第二行
>>> y[1, :]
array([4, 5, 6, 7])
>>> y[1, ...]
array([4, 5, 6, 7])
### 获取第三列
>>> y[:, 2]
array([ 2, 6, 10])
>>> y[..., 2]
array([ 2, 6, 10])
在这里冒号和省略号的功能是一致的。
切片操作
Numpy的切片操作与Python列表完全一致。[start_index : stop_index : step],默认第三个参数为1。具体可参考彻底搞懂Python切片操作
拷贝整个数组
在Numpy中提供了x[:]和x.copy()两种方式对数组进行拷贝。
>>> x = y[:]
>>> x
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> z = y.copy()
>>> z
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
但两种方式有本质的区别。
x = y[:]只是将x指向了y的内存地址,并没有重新分配内存空间,修改x的元素值会改变y相应位置的元素值。
z = y.copy()重新分配了内存空间,修改z的元素值不会改变y相应位置的元素值。
### 修改x,改变了y
>>> y[1, 1]
5
>>> x[1, 1] = 0
>>> y[1, 1]
0
### 修改z, y不变
>>> y[2, 2]
10
>>> z[2, 2] = 0
>>> y[2, 2]
10
增加/降低数组维度
有时候,数据处理的过程中,常常会遇到两个数据的shape不匹配的情况。例如一张256 * 256的灰度图,尺寸可能是(256, 256)或者(256, 256, 1),将(256, 256)转换成(256, 256, 1)称为增维,有以下几种方法可以完成。
>>> x = np.arange(256 * 256).reshape(256, 256)
>>> x.shape
(256, 256)
### 第一种方法,直接使用reshape
>>> y = x.reshape(256, 256, 1)
>>> y.shape
(256, 256, 1)
### 第二种方法,这里np.newaxis = None
>>> z = x[:, :, np.newaxis]
>>> z.shape
(256, 256, 1)
### 同时可以将np.newaxis放在其他位置,这样相应的位置就会增加一个维度,长度为1
>>> a = x[:, np.newaxis, :]
>>> a.shape
(256, 1, 256)
降维的话,也可以直接使用reshape完成。
>>> y.shape
(256, 256, 1)
>>> y.reshape(256, 256).shape
(256, 256)