一.数组切片
ndarray 对象的内容可以通过索引或切片来访问和修改,与 Python 中 list
的切片操作一样。
a[x , y],x 为行索引,y 为列索引。x,y的格式都是 a : b : c ,其中 a,b,c 为整数,a 为起始索引,b 为结束索引,c 为步长。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import numpy a = numpy.array([[1,2,3],[4, 5, 6]])
print(a[:,0:2])
print(a[0,0:2])
b = a[0,0:2] b[:] = 1 print(b) print(a)
|
结果:
1 2 3 4 5 6
| [[1 2] [4 5]] [1 2] [1 1] [[1 1 3] [4 5 6]]
|
二.高级索引
2.1 整数数组索引
就是把数组中元素的横纵坐标取出来,所有要取的元素的横坐标
放在一个列表中,纵坐标
放在另一个列表中,然后将两个列表整合成
一个数组,用这个数组作为下标
访问就可以得到想要的值了。
看到这里是不是觉得有点懵,没事,举个例子就明白了:
1 2 3 4 5 6 7 8 9
| import numpy as np
a = numpy.array([[1,2,3],[4, 5, 6]])
print(a[[0,0],[0,1]])
|
结果:
也就是说,先根据数组形状,在脑子里构建一个坐标系。你要取什么元素,就把这个元素的横坐标单独取出来,纵坐标单独取出来,然后把这两个列表组合起来当成数组下标就能拿到了你想要的元素了。
还有一个特殊情况,可以用简便方法:
1 2 3 4 5 6 7
| import numpy as np a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
print(a[[0,0,-1,-1],[0,-1,0,-1]])
|
结果:
2.2 布尔索引
通过布尔运算,来获取符合指定条件的元素的数组。
1 2 3 4 5 6 7 8 9 10
| import numpy as np a = np.array([1,2,3,5,6,7])
bool_idx = a > 2 print(bool_idx)
print(a[bool_idx])
|
结果:
1 2
| [False False True True True True] [3 5 6 7]
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import numpy as np
a = np.array([[1,2,3],[4,5,6],[7,8,9]]) print(a)
print()
print(a[a>4])
|
结果:
1 2 3 4 5
| [[1 2 3] [4 5 6] [7 8 9]]
[5 6 7 8 9]
|
大的来了——:
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 27 28 29
| import numpy as np
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(a[a[...,2] > 3])
print()
print(a[a[2,...] > 7])
|
结果:
1 2 3 4 5
| [[4 5 6] [7 8 9]]
[[4 5 6] [7 8 9]]
|
1 2 3 4 5 6 7 8
| print(a[:, a[1] > 5])
print()
print(a[0:2,a[...,1] > 4])
|
结果:
1 2 3 4 5 6
| [[3] [6] [9]]
[[2 3] [5 6]]
|
这里有一个简单的理解方法:
a []
的括号中是要放表达式的,可能既有行也有列,当其中一个地方(行或列)填表达式时,可以先解读表达式的结果,然后把结果代入另一个列(或行)的切片去找到满足表达式的值。
同时,布尔运算也能加上逻辑运算符,各个条件要加上():
&:与运算,组合多个条件。
|:或运算,组合多个条件。
~:非运算,取反条件。
2.3 提取数组主对角线元素
使用 diag()
方法
1 2 3 4
| import numpy as np a = np.array([[1,2,3],[4,5,6],[7,8,9]]) print(np.diag(a))
|
结果:
三.广播
是 numpy 对不同形状(shape)的数组进行数值计算的方式,要求维数相同,且各维度的长度相同,如果不相同,可以通过广播机制,这种机制的核心是对形状较小的数组,在横向或纵向上进行一定次数的重复,使其与形状较大的数组拥有相同的维度。
1 2 3 4 5 6 7 8
| import numpy a = numpy.array([1,2,3]) b = numpy.array([[4,5,6],[7,8,9]]) print(a + b)
|
结果:
可以看到,a的形状是 (3,) ,b的形状是 (2,3) ,a会通过广播机机制复制自身增加维度让自己的形状变成(2,3),这样a和b的形状就匹配了。
1 2 3 4 5 6 7 8
| import numpy a = numpy.array([1,2,3]) b = numpy.array([[1],[2]]) print(a+b)
|
结果:
维度不匹配的时候,先看看其中一个数组的每个维度中是否只有一个元素或没有元素,如果是的话,那么就自动扩展这个维度长度;如果没有元素就向高维扩展(形状(2,2)往前面扩展为(1,2,2))依次扩展其他维度。这里就是把b数组中的[1]
扩展成[1 1 1]
,[2]
扩展成[2 2 2]
。然后就变成了长度匹配的做法了。
1 2 3 4 5 6 7 8
| import numpy as np a = np.array([1, 2, 3, 4])
print(a + 1)
|
结果:
其余大多数情况,都是不能进行广播的,比如:
1 2 3 4 5 6 7 8 9
| import numpy as np
a = np.array([1, 2, 3])
b = np.array([[1, 2], [4, 5]]) print(a+b)
|
结果:
1 2 3 4 5 6 7 8
| --------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[26], line 6 3 a = np.array([1, 2, 3]) 5 b = np.array([[1, 2], [4, 5]]) ----> 6 print(a+b)
ValueError: operands could not be broadcast together with shapes (3,) (2,2)
|
也就是两个数组行列至少有一边长度相同,另一边长度为1;或俩都有一边长度为1;或一个数组的几个维度长度全为1,这样才可以进行广播相加。
四.数组遍历
4.1 遍历数组的第一维度
遍历数组的第一维度,即按行或列的顺序逐个访问元素,返回的是数组的子数组(如行或列),而不是单个元素。
1 2 3 4 5 6 7
| import numpy as np a = np.array([[1, 2, 3],[4,5,6]])
for i in a: print(i)
|
结果:
4.2 nditer逐个访问元素
是 NumPy 中的一个强大的迭代器对象,其中有两个重要参数:order
、flags
order
参数用于指定数组的遍历顺序。默认情况下,nditer 按照 C 风格(行优先)遍历数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import numpy as np a = np.array([[1, 2, 3],[4, 5, 6]])
for i in np.nditer(a,order='F'): print(i)
print()
for i in np.nditer(a,order='C'): print(i)
|
结果:
1 2 3 4 5 6 7 8 9 10 11 12 13
| 1 4 2 5 3 6
1 2 3 4 5 6
|
flags
参数用于指定迭代器的额外行为,一般配合新建变量来使用
1 2 3 4 5 6 7 8
| import numpy as np a = np.array([[1, 2, 3],[4, 5, 6]])
x = np.nditer(a,flags = ['multi_index']) for i in x: print(i,x.multi_index)
|
结果:
1 2 3 4 5 6
| 1 (0, 0) 2 (0, 1) 3 (0, 2) 4 (1, 0) 5 (1, 1) 6 (1, 2)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
x = np.nditer(a,flags = ['external_loop'],order='C')
y = np.nditer(a,flags = ['external_loop'],order='F') for i in x: print(i)
print() for i in y: print(i)
|
结果:
1 2 3 4 5
| [1 2 3 4 5 6]
[1 4] [2 5] [3 6]
|