1、切片和索引
ndarray对象的内容可以通过索引或切片来访问和修改,与Python中list的切片操作一样
ndarray数组可以基于0-n的下标进行索引,切片对象可以通过内置的slice函数,并设置start,stop及step参数进行,从原数组中切割出一个新的数组
import numpy as np
arr = np.logspace(1.0, 2.0, 10)
print(arr)
# 方法一:使用:冒号进行数组切割
print(arr[2:9:2]) # 从索引2开始到索引7停止,间隔为2
# 方法二:使用slice函数
s = slice(2,9,2)
print(arr[s])
[ 10. 12.91549665 16.68100537 21.5443469 27.82559402
35.93813664 46.41588834 59.94842503 77.42636827 100. ][16.68100537 27.82559402 46.41588834 77.42636827]
切片还可以包含省略号…,来使选择元组的长度与数组的维度相同。如果在行位置使用省略号,它将返回包含行中元素的ndarray
import numpy as np
arr = np.arange(1, 16)
arr1 = arr.reshape(5, 3)
print(arr1)
print(arr1[..., 1])
print(arr1[..., 1:])
print(arr1[1, ...])
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]
[13 14 15]][ 2 5 8 11 14]
[[ 2 3]
[ 5 6]
[ 8 9]
[11 12]
[14 15]][[ 4 5 6]]
2、高级索引
Numpy比一般的Python序列提供更多的索引方式。除了之前看到的用整数和切片的索引外,数组可以由整数数组索引、布尔索引
整数数组索引
import numpy as np
arr = np.arange(1, 10)
arr1 = arr.reshape(3, 3)
print(arr1)
# (0,0) (1,1) (2,0)
print(arr1[[0, 1, 2], [0, 1, 0]])
[[1 2 3]
[4 5 6]
[7 8 9]]
[1 5 7]
布尔索引
布尔索引通过布尔运算来获取符合指定条件的元素的数组
- 打印大于5的元素
import numpy as np
arr = np.arange(0, 12)
arr1 = arr.reshape(3, 4)
print(arr1[arr1 > 5])
[ 6 7 8 9 10 11]
- 使用了~(取补运算符)来过滤NaN
import numpy as np
arr3 = np.array([np.nan, 1, 2, np.nan, 3, 4, 5])
print(arr3[~np.isnan(arr3)])
[1. 2. 3. 4. 5.]
3、广播
是numpy对不同形状(shape)的数组进行数值计算的方式,对数组的算术运算通常在相应的元素上进行
形状相同
如果两个数组a和b形状相同,即满足a.shape==b.shape,那么a+b的结果就是a与b数组对应位相加。
import numpy as np
arr1 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
arr2 = np.array([[9, 10, 11, 12], [13, 14, 15, 16]])
print(f"arr1 + arr2 : \n{arr1 + arr2}")
arr1 + arr2 :
[[10 12 14 16]
[18 20 22 24]]
形状不同
如果两个数组的维数不相同,则元素到元素的操作是不可能的。 然而,在numpy中仍然可以对形状不相似的数组进行操作,因为它拥有广播功能。较小的数组会广播到较大数组的大小,以便使它们的形状可兼容。
import numpy as np
arr2 = np.array([[9, 10, 11, 12], [13, 14, 15, 16]])
arr3 = np.array([1, 2, 3, 4])
print("arr3 + arr2:\n", (arr3 + arr2))
arr3 + arr2:
[[10 12 14 16]
[14 16 18 20]]
广播的规则
-
让所有输入数组都向其中形状最长的数组看起,形状中不足的部分通过前面加1补齐
-
输出数组的形状是输入数组形状的各个维度上的最大值
-
如果输入数组的某个维度和输出数组的对应维度的长度相同或者其长度为1时,这个数组能够用来计算
-
当输入数组的某个维度的长度为1时,沿着此维度运算时都用此维度上的第一组值
简单理解
对两个数组,分别比较他们的每一个维度(若其中一个数组没有当前维度则忽略),满足
数组拥有相同形状
当前维度的值相等
当前维度的值有一个是1
若不满足:抛出“operands could not be broadcast together with shapes (2,4) (4,4) “异常
4、迭代
numpy.nditer基本使用
它是一个有效的多维迭代器对象,可以用在数组上进行迭代。数组的每个元素可使用Python的标准iterator接口来访问
import numpy as np
arr2 = np.array([[9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24]])
for x in np.nditer(arr2):
print(x, end=",")
print("")
9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
行优先与列优先
import numpy as np
print(arr)
# 行优先
for x in np.nditer(arr, order='C'):
print(x, end=",")
print("")
# 列优先
for x in np.nditer(arr, order='F'):
print(x, end=",")
[[ 2 4 6 8 10]
[12 14 16 18 20]]2,4,6,8,10,12,14,16,18,20,
2,12,4,14,6,16,8,18,10,20,
op_flags属性
import numpy as np
# op_flags默认是只读;使用readwrite进行读写
for x in np.nditer(arr, order='F', op_flags=["readwrite"]):
# x[...]可以为当前迭代位置的元素
x[...] = x ** 2
print(x[...], end=",")
4,144,16,196,36,256,64,324,100,400,
使用外部循环
nditer类的构造器拥有flags参数,它可以接受下列值:
参数 | 描述 |
---|---|
c_index | 可以跟踪C顺序的索引 |
f_index | 可以跟踪Fortran顺序的索引 |
milti_index | 每次迭代可以跟踪一种索引类型 |
external_loop | 给出的值时具有多个值的一维数组,而不是零维数组 |
import numpy as np
for x in np.nditer(arr, order='C',flags=['external_loop']):
print(x, end=",")
print("\n=====================")
for x in np.nditer(arr, order='F',flags=['external_loop']):
print(x, end=",")
[ 2 4 6 8 10 12 14 16 18 20],
=====================
[ 2 12],[ 4 14],[ 6 16],[ 8 18],[10 20],
广播迭代
如果两个数组是可以广播的,nditer组合对象能够同时迭代它们。
import numpy as np
arr1 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
# arr2 = np.array([[9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24]])
arr2 = np.array([[9, 10, 11, 12], [13, 14, 15, 16]])
# 注意使用[]中括号来表示是一个数组
for x, y in np.nditer([arr1, arr2]):
print(x, ":", y, end=",")
print("")
1 : 9,2 : 10,3 : 11,4 : 12,5 : 13,6 : 14,7 : 15,8 : 16,
------ 以上内容均为学习笔记仅供参考,如有不准确或错误内容,望您批评指教。