使用操作符运算
大部分数学计算都是逐元素进行的。
import numpy as npa = np.array([1, 2, 3])b = np.ones(3, dtype=np.int)# 数组之间的加法c = a + bprint(c) # [2 3 4]# 直接和常数运算(广播机制)d = a * 3print(d) # [3 6 9]# 乘方运算e = a**4e_ = np.power(a, 4) # 使用内置的乘方函数 np.power()print(e, e_) # [ 1 16 81] [ 1 16 81]# 混合计算m = (10 * (a + b / 2)) > 20print(m) # [False True True]
在矩阵计算中,通常会使用另外一种乘法,这种乘法不是逐元素进行的。
import numpy as npA = np.array([[1, 1], [0, 1]])B = np.array([[2, 0], [3, 4]])print(A * B) # 逐元素相乘# [[2 0]# [0 4]]print(A @ B) # 矩阵的乘法# [[5 4]# [3 4]]print(A.dot(B)) # 另外一种写法# [[5 4]# [3 4]]
上面的所有计算,都没有直接在参与运算的数组上进行修改,而是生成了新的数组作为计算结果。Python中的一些赋值运算符+=和*=也可以用于NumPy数组对象。
import numpy as npa = np.array([[1, 2], [3, 4]], dtype=float)b = np.ones((2,2))a += bprint(a)# [[2. 3.]# [4. 5.]]
在上面这个例子中,将a加上b的结果又直接赋值给了a,没有生成新的存储空间来存放结果。a数组的构建过程中特别强调了元素存储类型是浮点型,目的是为了和b中元素类型保持一致(前面数组构建的部分介绍了np.ones()方法,其构建的数组存储类型是浮点型的)。
因为在NumPy数组中,元素存储的方式是按照C语言的规则进行的,这就表明每个元素的存储空间是固定好的,不能动态更改了,如果不同类型的元素进行运算和赋值,就涉及到类型转换问题。
如果将浮点型的数据转换为整形,有可能丢失精度。在NumPy中,这种转换并不会自动触发,要我们手动处理。
a = np.array([[1, 2], [3, 4]]) # 整形b = np.ones((2,2)) # 浮点型a += b # 会抛异常# TypeError: Cannot cast ufunc add output from dtype('float64') to dtype('int32') with casting rule 'same_kind'
如果是低精度类型转换为高精度类型,这种情况NumPy是会自动帮我们处理的。
a = np.array([[1, 2], [3, 4]]) # 整形b = np.ones((2,2)) # 浮点型b += a # 注意是把 a 加到 b 上print(b.dtype) # float64print(b)# [[2. 3.]# [4. 5.]]
使用类方法运算
import numpy as npa = np.arange(15).reshape(3, 5)print(a.min()) # 0print(a.max()) # 14print(a.sum()) # 105print(a.mean()) # 7.0
这种计算模式一般都是在数组内部进行的,和一些特征相关。函数内部通常还可以指定运算限定的维度(轴),不再对整个数组元素进行计算。
import numpy as npa = np.arange(15).reshape(3, 5)# [[ 0 1 2 3 4]# [ 5 6 7 8 9]# [10 11 12 13 14]]print(a.sum(axis=0)) # [15 18 21 24 27] 所有列元素相加,结果组成新的数组print(a.sum(axis=1)) # [10, 35, 60] 行元素相加print(a.mean(axis=0)) # [5. 6. 7. 8. 9.]

怎样理解 axis 参考 这里,更多的类计算方法可以参阅 这里。
通用计算方法
通用计算方法可以理解为是NumPy为数组提供的数学函数,像上面已经使用过的np.power()函数。还有np.sin(),np.exp()等。这些函数在数组上也是逐元素进行计算,生成新的结果数组。
import numpy as np# 三角函数计算p = np.array([np.pi / 2, np.pi / 6])q = np.sin(p)print(q) # [1. 0.5]# e 的幂运算a = np.arange(3)print(np.exp(a)) # [1. 2.71828183 7.3890561 ]
更多的计算方法可以参考 这里。
