Numpy 索引与切片

索引

一维索引

数组上的算术运算符会应用到 元素 级别。下面是创建一个新数组并填充结果的示例:

>>>import numpy as np
>>>A = np.arange(3,15) #array([ 3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])
>>>A[0]
3
>>>A[1]
4

为了获取数组的末尾元素,可以使用负值索引

>>>A[-1]
14
>>>A[11]
14

二/多维索引

>>>B = np.arange(12).reshape(3,4)
'''array([[ 0,  1,  2,  3],
          [ 4,  5,  6,  7],
          [ 8,  9, 10, 11]])'''
>>>B[0]
array([0, 1, 2, 3])
>>>B[0][0]
0
>>>B[0,0]    		#与B[0][0]等价
0

逐行打印

for row in B:
    print(row)
"""    
[ 0,  1,  2,  3]
[ 4,  5,  6,  7]
[ 8,  9, 10, 11]
"""

逐列打印

如果要逐列打印,我们需要用到一点小trick,将B进行转置(B.T 即可完成),再打印

for column in B.T:
    print(column)
"""  
[0 	 4 	  8]
[1 	 5 	  9]
[2   6   10]
[3   7   11]
"""

逐元素打印

import numpy as np
A = np.arange(3,15).reshape((3,4))
         
print(A.flatten())   
# array([3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])

for item in A.flat:
    print(item)
    
# 3
# 4
……
# 14

这一脚本中的flatten是一个展开性质的函数,将多维的矩阵进行展开成1行的数列。而flat是一个迭代器,本身是一个object属性。

切片

正如此前用中括号获取单个数组元素,我们也可以用切片(slice)符号获取子数组,切片符号用冒号(:)表示。NumPy切片语法和Python的标准切片语法相同。为了获取数组x的一个切片,可以采用如下方式:

x[start:stop:step]

即,从索引start开始,以step为步长,到stop为止,不包括stop

如果以上3个参数都未指定,那么它们将会被分别默认设置为start=0, stop=维度的大小(size of dimension)和step=1

1 一维子数组

>>>x = np.arange(10) #array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>>x[:5]	#前5个元素
array([0, 1, 2, 3, 4])
>>>x[5:]	#索引5之后的元素
array([5, 6, 7, 8, 9])
>>>x[4:7]	#中间的子数组
array([4, 5, 6])
>>>x[::2]	#每隔一个元素 或 理解为取偶数下标的元素
array([0, 2, 4, 6, 8])
>>>x[1::2]	#每隔一个元素,从索引1开始
array([1, 3, 5, 7, 9])

步长为负值的情况

>>>x[::-1]		#所有元素,逆序的
array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
>>>x[5::-2]		#从索引5开始,每隔一个元素逆序
array([5, 3, 1])

2 二/多维子数组

>>>x2 = np.array([[12,5,2,4],
				  [7,6,8,8],
                  [1,6,7,7]])
>>>x2[:2, :3] #前两行,前三列
array([[12,  5,  2],
       [ 7,  6,  8]])
>>>x2[:3, ::2] #所有行,每隔一列
array([[12,  2],
       [ 7,  8],
       [ 1,  7]])

最后,子数组维度也可以同时被逆序

>>>x2[::-1, ::-1]
array([[ 7,  7,  6,  1],
       [ 8,  8,  6,  7],
       [ 4,  2,  5, 12]])

3 获取数组的行和列

一种常见的需求是获取数组的单行和单列。可以将索引与切片结合起来实现该功能,用一个冒号(:)表示空切片

>>>print(x2[:, 0])	#x2的第一列
[12  7  1]
>>>print(x2[0, :])	#x2的第一行
[12  5  2  4]

在获取时,出于语法的简洁考虑,可以省略空的切片

>>>print(x2[0])	#等价于x2[0, :]
[12  5  2  4]

4 浅拷贝/视图

数组切片有一点非常重要,那就是数组切片返回的是数组数据的视图(浅拷贝),而不是数值数据的副本(深拷贝)

>>>x2_sub = x2[:2, :2]
array([[12,  5],
       [ 7,  6]])

现在如果修改这个子数组,将会看到原始数组也被修改了!

>>>x2_sub[0,0] = 99
>>>print(x2_sub)
[[99  5]
 [ 7  6]]
>>>print(x2)
[[99  5  2  4]
[ 7  6  8  8]
[ 1  6  7  7]]

5 深拷贝/副本

>>>x2_sub = x2[:2, :2].copy()
array([[12,  5],
       [ 7,  6]])

如果修改这个子数组,原始数组不会被改变

>>>x2_sub[0,0] = 44
>>>print(x2_sub)
[[44  5]
 [ 7  6]]
>>>print(x2)
[[12  5  2  4]
 [ 7  6  8  8]
 [ 1  6  7  7]]

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦