使用操作符运算
大部分数学计算都是逐元素进行的。
import numpy as np
a = np.array([1, 2, 3])
b = np.ones(3, dtype=np.int)
# 数组之间的加法
c = a + b
print(c) # [2 3 4]
# 直接和常数运算(广播机制)
d = a * 3
print(d) # [3 6 9]
# 乘方运算
e = a**4
e_ = np.power(a, 4) # 使用内置的乘方函数 np.power()
print(e, e_) # [ 1 16 81] [ 1 16 81]
# 混合计算
m = (10 * (a + b / 2)) > 20
print(m) # [False True True]
在矩阵计算中,通常会使用另外一种乘法,这种乘法不是逐元素进行的。
import numpy as np
A = 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 np
a = np.array([[1, 2], [3, 4]], dtype=float)
b = np.ones((2,2))
a += b
print(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) # float64
print(b)
# [[2. 3.]
# [4. 5.]]
使用类方法运算
import numpy as np
a = np.arange(15).reshape(3, 5)
print(a.min()) # 0
print(a.max()) # 14
print(a.sum()) # 105
print(a.mean()) # 7.0
这种计算模式一般都是在数组内部进行的,和一些特征相关。函数内部通常还可以指定运算限定的维度(轴),不再对整个数组元素进行计算。
import numpy as np
a = 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 ]
更多的计算方法可以参考 这里。