Indexing on Numpys can be sorted in the following three ways:
Basic Indexing
Single element indexing
Slicing and striding
Advanced Indexing
field access.
In this article, we will go through the basic indexing of NumPy arrays.
Some basic rules should also be beared in your mind.
基础数字索引会减少维度
假设 array's shape = (1,2,3) -> ndim = 3, 设: index = [:,0,:], 得 result_shape = (1,3);
由此可知,维度减少1, 指定的维度 ndim = 1 (即[:,0,:], 0对应的维度), 所以只保留 ndim = 0, ndim = 2 的长度, 也即(1,3)
具体可以参考下面的demo
单纯切片不会改变维度
如果选择元组的所有条目都是:,除了第p个条目是切片对象i:j:k,那么返回的数组具有维度N,该维度是通过沿第p个轴堆叠
在 NumPy 的基本切片(basic slicing)中,当切片元组里有多个“非 :”条目(例如整数索引或切片对象),NumPy 会把这些非 : 条目依次应用,相当于先按第一个非 : 条目做一次切片得到子数组,然后在子数组上继续用下一个非 : 条目(其它位置都用 : 替代)。因此x[ind1, …, ind2, :] 在基本切片下等价于 x[ind1][…, ind2, :]
Basic Indexing
Single element indexing
Single element indexing works exactly like in Python lists.
1 2 3 4 arr = np.arange(10 ).reshape(2 ,5 )print (arr)
[[0 1 2 3 4]
[5 6 7 8 9]]
1 2 3 4 b = arr[0 ]print (b)print (b.shape)
[0 1 2 3 4]
(5,)
1 2 3 4 5 c = arr[..., 3 ]print (c)print (c.shape)
[3 8]
(2,)
当选择某一个维度时,返回的子数组形状会减少这个维度,而其他维度的大小保持不变.
It must to be noted that the returned array is a view.
Slicing and striding in NumPy
Basic slicing are always views of the original array.
Numpy 的切片和步长,主要通过的是 slice 对象来实现的(start:stop:step)。
Numpy数组的切片操作返回的是原数组的视图(View),而不是副本。这里跟Python内置序列不同,Python的切片操作返回的是全新副本(copy)。
1 2 3 4 5 6 7 8 s = slice (2 , 5 , 2 )print (s) arr = np.array([1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ])print (arr[s])print (arr[2 :5 :2 ])
slice(2, 5, 2)
[3 5]
[3 5]
1 2 3 4 arr = np.arange(27 ).reshape(3 , 3 , 3 )print (arr)print (f"arr.ndim: {arr.ndim} " )print (f"arr.shape: {arr.shape} " )
[[[ 0 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]]]
arr.ndim: 3
arr.shape: (3, 3, 3)
3
3
1 2 3 d = arr[:,2 ,:] d.ndim d
array([[ 6, 7, 8],
[15, 16, 17],
[24, 25, 26]])
If the selection tuple has all entries : except the p-th entry which is a slice object i:j:k, then the returned array has dimension N formed by stacking, along the p-th axis, the sub-arrays returned by integer indexing of elements i, i+k, …, i + (m - 1) k < j.
如果选择元组的所有条目都是:,除了第p个条目是切片对象i:j:k,那么返回的数组具有维度N,该维度是通过沿第p 个轴堆叠
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 e = arr[:, 0 :2 :1 ,:]print (f"e.ndim: {e.ndim} " )print (e) e_1 = arr[:, 0 , :]print (f"e_1:{e_1} " ) e_2 = arr[:, 1 , :]print (f"e_2:{e_2} " ) e_3 = np.stack((e_1, e_2), axis=1 )print (f"e_3: \n{e_3} " )
e.ndim: 3
[[[ 0 1 2]
[ 3 4 5]]
[[ 9 10 11]
[12 13 14]]
[[18 19 20]
[21 22 23]]]
e_1:[[ 0 1 2]
[ 9 10 11]
[18 19 20]]
e_2:[[ 3 4 5]
[12 13 14]
[21 22 23]]
e_3:
[[[ 0 1 2]
[ 3 4 5]]
[[ 9 10 11]
[12 13 14]]
[[18 19 20]
[21 22 23]]]
Basic slicing with more than one non-: entry in the slicing tuple, acts like repeated application of slicing using a single non-: entry, where the non-: entries are successively taken (with all other non-: entries replaced by :). Thus, x[ind1, …, ind2,:] acts like x[ind1][…, ind2, :] under basic slicing.
在 NumPy 的基本切片(basic slicing)中,当切片元组里有多个“非 :”条目(例如整数索引或切片对象),NumPy 会把这些非 : 条目依次应用,相当于先按第一个非 : 条目做一次切片得到子数组,然后在子数组上继续用下一个非 : 条目(其它位置都用 : 替代)。因此
x[ind1, …, ind2, :] 在基本切片下等价于 x[ind1][…, ind2, :]
这是“逐步应用”的效果,不是一次性在原数组上并行处理。
效果受索引类型影响:整数索引会减少维度(返回子数组时维度被移除),切片则保留维度。
这是基本切片(basic slicing);扩展切片若使用高级索引(如整数数组、布尔数组),规则不同。
1 2 3 4 5 6 7 8 9 arr = np.arange(2 *3 *4 ).reshape(2 ,3 ,4 )print (arr)print ("----" ) a = arr[0 :2 , 1 , :] b = arr[0 :2 ][..., 1 , :] print (a)print ("----" )print (np.array_equal(a, b)) print (b)
[[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]]
----
[[ 4 5 6 7]
[16 17 18 19]]
----
True
[[ 4 5 6 7]
[16 17 18 19]]
1 2 3 4 5 c = arr[1 , 0 :2 , :]print (c) d = arr[1 ][..., 0 :2 , :]print (np.array_equal(c, d)) print (d)
[[12 13 14 15]
[16 17 18 19]]
True
[[12 13 14 15]
[16 17 18 19]]
... Ellipisis represents the remaining dimensions that you can index into.
newaxis increases the dimension of the existing array by one more dimension. 主要做改变shape使用
1 arr = np.arange(2 * 3 * 4 ).reshape(2 , 3 , 4 )
(2, 3, 4)
array([[ 0, 4, 8],
[12, 16, 20]])
1 2 3 4 5 6 d_1 = arr[:, :, 0 ] d_1
array([[ 0, 4, 8],
[12, 16, 20]])
1 2 3 li = [arr[0 ,0 ,0 ], arr[0 ,1 ,0 ], arr[0 ,2 ,0 ], arr[1 ,0 ,0 ], arr[1 ,1 ,0 ], arr[1 ,2 ,0 ]] d_2 = np.array(li).reshape(2 ,3 ) d_2
array([[ 0, 4, 8],
[12, 16, 20]])
1 2 result = np.array_equal(d, d_1) result
True
1 2 3 4 5 arr = np.array([1 , 2 , 3 , 4 , 5 ])print (arr) print (arr.shape)
[1 2 3 4 5]
(5,)
1 2 3 4 5 6 arr_new = arr[np.newaxis, :] arr_new_alias = arr[None , :] print (arr_new) print (np.array_equal(arr_new, arr_new_alias)) print (arr_new.shape)
[[1 2 3 4 5]]
True
(1, 5)
1 2 3 4 arr_new = arr[np.newaxis, np.newaxis, :] print (arr_new) print (arr_new.shape)
[[[1 2 3 4 5]]]
(1, 1, 5)
1 2 3 4 arr_new = arr[:, np.newaxis] print (arr_new)print (arr_new.shape)
[[1]
[2]
[3]
[4]
[5]]
(5, 1)
1 2 3 arr_new = arr[np.newaxis, :, np.newaxis] print (arr_new) print (arr_new.shape)
[[[1]
[2]
[3]
[4]
[5]]]
(1, 5, 1)