使用操作符运算

大部分数学计算都是逐元素进行的。

  1. import numpy as np
  2. a = np.array([1, 2, 3])
  3. b = np.ones(3, dtype=np.int)
  4. # 数组之间的加法
  5. c = a + b
  6. print(c) # [2 3 4]
  7. # 直接和常数运算(广播机制)
  8. d = a * 3
  9. print(d) # [3 6 9]
  10. # 乘方运算
  11. e = a**4
  12. e_ = np.power(a, 4) # 使用内置的乘方函数 np.power()
  13. print(e, e_) # [ 1 16 81] [ 1 16 81]
  14. # 混合计算
  15. m = (10 * (a + b / 2)) > 20
  16. print(m) # [False True True]

在矩阵计算中,通常会使用另外一种乘法,这种乘法不是逐元素进行的。

  1. import numpy as np
  2. A = np.array([[1, 1], [0, 1]])
  3. B = np.array([[2, 0], [3, 4]])
  4. print(A * B) # 逐元素相乘
  5. # [[2 0]
  6. # [0 4]]
  7. print(A @ B) # 矩阵的乘法
  8. # [[5 4]
  9. # [3 4]]
  10. print(A.dot(B)) # 另外一种写法
  11. # [[5 4]
  12. # [3 4]]

上面的所有计算,都没有直接在参与运算的数组上进行修改,而是生成了新的数组作为计算结果。Python中的一些赋值运算符+=*=也可以用于NumPy数组对象。

  1. import numpy as np
  2. a = np.array([[1, 2], [3, 4]], dtype=float)
  3. b = np.ones((2,2))
  4. a += b
  5. print(a)
  6. # [[2. 3.]
  7. # [4. 5.]]

在上面这个例子中,将a加上b的结果又直接赋值给了a,没有生成新的存储空间来存放结果。a数组的构建过程中特别强调了元素存储类型是浮点型,目的是为了和b中元素类型保持一致(前面数组构建的部分介绍了np.ones()方法,其构建的数组存储类型是浮点型的)。

因为在NumPy数组中,元素存储的方式是按照C语言的规则进行的,这就表明每个元素的存储空间是固定好的,不能动态更改了,如果不同类型的元素进行运算和赋值,就涉及到类型转换问题。

如果将浮点型的数据转换为整形,有可能丢失精度。在NumPy中,这种转换并不会自动触发,要我们手动处理。

  1. a = np.array([[1, 2], [3, 4]]) # 整形
  2. b = np.ones((2,2)) # 浮点型
  3. a += b # 会抛异常
  4. # TypeError: Cannot cast ufunc add output from dtype('float64') to dtype('int32') with casting rule 'same_kind'

如果是低精度类型转换为高精度类型,这种情况NumPy是会自动帮我们处理的。

  1. a = np.array([[1, 2], [3, 4]]) # 整形
  2. b = np.ones((2,2)) # 浮点型
  3. b += a # 注意是把 a 加到 b 上
  4. print(b.dtype) # float64
  5. print(b)
  6. # [[2. 3.]
  7. # [4. 5.]]

使用类方法运算

  1. import numpy as np
  2. a = np.arange(15).reshape(3, 5)
  3. print(a.min()) # 0
  4. print(a.max()) # 14
  5. print(a.sum()) # 105
  6. print(a.mean()) # 7.0

这种计算模式一般都是在数组内部进行的,和一些特征相关。函数内部通常还可以指定运算限定的维度(轴),不再对整个数组元素进行计算。

  1. import numpy as np
  2. a = np.arange(15).reshape(3, 5)
  3. # [[ 0 1 2 3 4]
  4. # [ 5 6 7 8 9]
  5. # [10 11 12 13 14]]
  6. print(a.sum(axis=0)) # [15 18 21 24 27] 所有列元素相加,结果组成新的数组
  7. print(a.sum(axis=1)) # [10, 35, 60] 行元素相加
  8. print(a.mean(axis=0)) # [5. 6. 7. 8. 9.]

image.png
怎样理解 axis 参考 这里,更多的类计算方法可以参阅 这里

通用计算方法

通用计算方法可以理解为是NumPy为数组提供的数学函数,像上面已经使用过的np.power()函数。还有np.sin()np.exp()等。这些函数在数组上也是逐元素进行计算,生成新的结果数组。

  1. import numpy as np
  2. # 三角函数计算
  3. p = np.array([np.pi / 2, np.pi / 6])
  4. q = np.sin(p)
  5. print(q) # [1. 0.5]
  6. # e 的幂运算
  7. a = np.arange(3)
  8. print(np.exp(a)) # [1. 2.71828183 7.3890561 ]

更多的计算方法可以参考 这里