NumPy之:ndarray中的函式
簡介
在NumPy中,多維陣列除了基本的算數運算之外,還內建了一些非常有用的函式,可以加快我們的科學計算的速度。
簡單函式
我們先看下比較常見的運算函式,在使用之前,我們先構造一個陣列:
arr = np.arange(10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
計算陣列中元素的開方:
np.sqrt(arr)
array([0. , 1. , 1.4142, 1.7321, 2. , 2.2361, 2.4495, 2.6458,
2.8284, 3. ])
自然常數e為底的指數函式:
np.exp(arr)
array([ 1. , 2.7183, 7.3891, 20.0855, 54.5982, 148.4132,
403.4288, 1096.6332, 2980.958 , 8103.0839])
取兩個陣列的最大值,組成新的陣列:
x = np.random.randn(8)
y = np.random.randn(8)
x,y
(array([-2.3594, -0.1995, -1.542 , -0.9707, -1.307 , 0.2863, 0.378 ,
-0.7539]),
array([ 0.3313, 1.3497, 0.0699, 0.2467, -0.0119, 1.0048, 1.3272,
-0.9193]))
np.maximum(x, y)
array([ 0.3313, 1.3497, 0.0699, 0.2467, -0.0119, 1.0048, 1.3272,
-0.7539])
返 回浮點數陣列的小數和整數部分:
arr = np.random.randn(7) * 5
array([-7.7455, 0.1109, 3.7918, -3.3026, 4.3129, -0.0502, 0.25 ])
remainder, whole_part = np.modf(arr)
(array([-0.7455, 0.1109, 0.7918, -0.3026, 0.3129, -0.0502, 0.25 ]),
array([-7., 0., 3., -3., 4., -0., 0.]))
向量化陣列運算
如果要進行陣列之間的運算,常用的方法就是進行迴圈遍歷,但是這樣的效率會比較低。所以Numpy提供了陣列之間的資料處理的方法。
先來講解一下 np.meshgrid 這個函式,這個函式是用來快速生成網格點座標矩陣的。
先看一段座標點的程式碼:
import numpy as np
import matplotlib.pyplot as plt
x = np.array([[0, 1, 2], [0, 1, 2]])
y = np.array([[0, 0, 0], [1, 1, 1]])
plt.plot(x, y,
color='green',
marker='.',
linestyle='')
plt.grid(True)
plt.show()
上面的X是一個二維陣列,表示的是座標點的X軸的位置。
Y也是一個二維陣列,表示的是座標點的Y軸的位置。
看下畫出來的影像:
上面畫出的就是使用X,Y矩陣組合出來的6個座標點。
上面的X,Y的二維陣列是我們手動輸入的,如果座標上面有大量點的話,手動輸入肯定是不可取的。
於是有了np.meshgrid這個函式。這個函式可以接受兩個一維的陣列,然後生成二維的X,Y座標矩陣。
上面的例子可以改寫為:
x = np.array([0,1,2])
y = np.array([0,1])
xs, ys = np.meshgrid(x, y)
xs,ys
(array([[0, 1, 2],
[0, 1, 2]]),
array([[0, 0, 0],
[1, 1, 1]]))
可以看到生成的xs和ys和手動輸入是一樣的。
有了網格座標之後,我們就可以基於網格值來計算一些資料,比如:\(sqrt(x^2+y^2)\) ,我們不用變數矩陣中所有的資料,只需要直接使用陣列進行運算即可:
np.sqrt(xs ** 2 + ys ** 2)
結果:
array([[0. , 1. , 2. ],
[1. , 1.41421356, 2.23606798]])
因為xs 和ys本身就是2 * 3 的矩陣,所以結果也是 2 * 3 的矩陣。
條件邏輯表示式
我們可以在構建陣列的時候使用條件邏輯表示式:
xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])
yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])
cond = np.array([True, False, True, True, False])
result = [(x if c else y)
for x, y, c in zip(xarr, yarr, cond)]
result
[1.1, 2.2, 1.3, 1.4, 2.5]
更簡單一點,我們可以使用where語句:
result = np.where(cond, xarr, yarr)
result
array([1.1, 2.2, 1.3, 1.4, 2.5])
我們還可以根據where的條件來修改陣列的值:
arr = np.random.randn(4, 4)
arr
array([[ 0.7953, 0.1181, -0.7485, 0.585 ],
[ 0.1527, -1.5657, -0.5625, -0.0327],
[-0.929 , -0.4826, -0.0363, 1.0954],
[ 0.9809, -0.5895, 1.5817, -0.5287]])
上面我們構建了一個4 * 4 的陣列。
我們可以在where中進行資料的比較,如果大於0,將資料修改成2 ,如果小於0,則將資料修該成-2 :
np.where(arr > 0, 2, -2)
array([[ 2, 2, -2, 2],
[ 2, -2, -2, -2],
[-2, -2, -2, 2],
[ 2, -2, 2, -2]])
統計方法
numpy提供了mean,sum等統計方法:
arr = np.random.randn(5, 4)
arr
arr.mean()
np.mean(arr)
arr.sum()
還可以按維度來統計:
arr.mean(axis=1)
arr.sum(axis=0)
cumsum進行累加計算:
arr = np.array([0, 1, 2, 3, 4, 5, 6, 7])
arr.cumsum()
array([ 0, 1, 3, 6, 10, 15, 21, 28])
cumprod進行累乘計算:
arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
arr
arr.cumsum(axis=0)
array([[ 0, 1, 2],
[ 3, 5, 7],
[ 9, 12, 15]])
arr.cumprod(axis=1)
array([[ 0, 0, 0],
[ 3, 12, 60],
[ 6, 42, 336]])
布林陣列
any用於測試陣列中是否存在一個或多個True,而all則檢查陣列中所有值是否都是True:
bools = np.array([False, False, True, False])
bools.any()
True
bools.all()
False
排序
使用sort可以對陣列進行排序,除了普通排序還可以按照特定的軸來進行排序:
arr = np.random.randn(6)
arr.sort()
array([-2.5579, -1.2943, -0.2972, -0.1516, 0.0765, 0.1608])
arr = np.random.randn(5, 3)
arr
arr.sort(1)
arr
array([[-0.8852, -0.4936, -0.1875],
[-0.3507, -0.1154, 0.0447],
[-1.1512, -0.8978, 0.8909],
[-2.6123, -0.8671, 1.1413],
[-0.437 , 0.3475, 0.3836]])
sort(1)指的是按照第二個軸來排序。
檔案
可以方便的將陣列寫入到檔案和從檔案中讀出:
arr = np.arange(10)
np.save('some_array', arr)
會將陣列存放到some_array.npy檔案中,我們可以這樣讀取:
np.load('some_array.npy')
還可以以無壓縮的方式存入多個陣列:
np.savez('array_archive.npz', a=arr, b=arr)
讀取:
arch = np.load('array_archive.npz')
arch['b']
如果想要壓縮,可以這樣:
np.savez_compressed('arrays_compressed.npz', a=arr, b=arr)
線性代數
如果我們使用普通的算數符來進行矩陣的運算的話,只是簡單的陣列中對應的元素的算數運算。如果我們想做矩陣之間的乘法的時候,可以使用dot。
一個 2 * 3 的矩陣 dot 一個3*2 的矩陣,最終得到一個2 * 2 的矩陣。
x = np.array([[1., 2., 3.], [4., 5., 6.]])
y = np.array([[6., 23.], [-1, 7], [8, 9]])
x
y
x.dot(y)
array([[ 28., 64.],
[ 67., 181.]])
或者可以這樣寫:
np.dot(x, y)
array([[ 28., 64.],
[ 67., 181.]])
還可以使用 @ 符號:
x @ y
array([[ 28., 64.],
[ 67., 181.]])
我們看下都有哪些運算:
乘積運算:
操作符 | 描述 |
---|---|
dot(a, b[, out]) | 矩陣點積 |
linalg.multi_dot(arrays, *[, out]) | 多個矩陣點積 |
vdot(a, b) | 向量點積 |
inner(a, b) | 兩個陣列的內積 |
outer(a, b[, out]) | 兩個向量的外積 |
matmul(x1, x2, /[, out, casting, order, …]) | 兩個矩陣的對應位的乘積 |
tensordot(a, b[, axes]) | 計算沿指定軸的張量點積 |
einsum(subscripts, *operands[, out, dtype, …]) | 愛因斯坦求和約定 |
einsum_path(subscripts, *operands[, optimize]) | 通過考慮中間陣列的建立,評估einsum表示式的最低成本收縮順序。 |
linalg.matrix_power(a, n) | 矩陣的冪運算 |
kron(a, b) | 矩陣的Kronecker乘積 |
分解運算:
操作符 | 描述 |
---|---|
linalg.cholesky(a) | Cholesky 分解 |
linalg.qr(a[, mode]) | 計算矩陣的qr因式分解 |
linalg.svd(a[, full_matrices, compute_uv, …]) | 奇異值分解 |
本徵值和本徵向量:
操作 | 描述 |
---|---|
linalg.eig(a) | 計算方陣的特徵值和右特徵向量。 |
linalg.eigh(a[, UPLO]) | 返回複數Hermitian(共軛對稱)或實對稱矩陣的特徵值和特徵向量。 |
linalg.eigvals(a) | 計算通用矩陣的特徵值。 |
linalg.eigvalsh(a[, UPLO]) | 計算複數Hermitian(共軛對稱)或實對稱矩陣的特徵值。 |
基準值:
操作 | 描述 |
---|---|
linalg.norm(x[, ord, axis, keepdims]) | 矩陣或向量範數 |
linalg.cond(x[, p]) | Compute the condition number of a matrix. |
linalg.det(a) | 矩陣行列式 |
linalg.matrix_rank(M[, tol, hermitian]) | 使用SVD方法返回陣列的矩陣秩 |
linalg.slogdet(a) | 計算陣列行列式的符號和(自然)對數。 |
trace(a[, offset, axis1, axis2, dtype, out]) | 返回沿陣列對角線的和。 |
求解和反轉:
操作 | 描述 |
---|---|
linalg.solve(a, b) | 求解線性矩陣方程或線性標量方程組。 |
linalg.tensorsolve(a, b[, axes]) | 對x求解張量方程'a x = b'。 |
linalg.lstsq(a, b[, rcond]) | 將最小二乘解返回線性矩陣方程 |
linalg.inv(a) | 計算矩陣的(乘法)逆。 |
linalg.pinv(a[, rcond, hermitian]) | 計算矩陣的(Moore-Penrose)偽逆。 |
linalg.tensorinv(a[, ind]) | 計算N維陣列的“逆”。 |
隨機數
很多時候我們都需要生成隨機數,在NumPy中隨機數的生成非常簡單:
samples = np.random.normal(size=(4, 4))
samples
array([[-2.0016, -0.3718, 1.669 , -0.4386],
[-0.5397, 0.477 , 3.2489, -1.0212],
[-0.5771, 0.1241, 0.3026, 0.5238],
[ 0.0009, 1.3438, -0.7135, -0.8312]])
上面用normal來得到一個標準正態分佈的4×4樣本陣列。
使用np.random要比使用Python自帶的隨機數生成器要快得多。
np.random可以指定生成隨機數的種子:
np.random.seed(1234)
numpy.random的資料生成函式使用了全域性的隨機種子。要避免 全域性狀態,你可以使用numpy.random.RandomState,建立一個 與其它隔離的隨機數生成器:
rng = np.random.RandomState(1234)
rng.randn(10)
本文已收錄於 http://www.flydean.com/10-python-numpy-func/
最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!