目錄
- 一、改變陣列的形狀
- 1.1 np.reshape()
- 1.2 np.ravel()
- 1.3 np.flatten()
- 二、(類)轉置操作
- 2.1 ndarray.T
- 2.2 np.swapaxes()
- 2.3 np.moveaxis()
- 三、合并陣列
- 3.1 np.concatenate()
- 3.2 np.stack()
- 3.3 np.block()
- 3.3 np.vstack()
- 3.4 np.hstack()
- 四、劃分陣列
- 4.1 np.split()
- 4.2 np.array_split()
- 4.3 np.vsplit()
- 4.4 np.hsplit()
- 五、反轉陣列
- 5.1 np.flip()
- 5.2 np.fliplr()
- 5.3 np.flipud()
一、改變陣列的形狀
| 函式 | 作用 |
|---|---|
| np.reshape(a, newshape) | a是陣列,newshape是整型元組;回傳newshape形狀的陣列 |
| np.ravel(a) | 展平成一維陣列;等價于np.reshape(a, -1) |
| np.flatten(a) | 效果和ravel一樣,但更推薦使用flatten |
1.1 np.reshape()
A = np.arange(6).reshape((2, 3))
print(A)
# [[0 1 2]
# [3 4 5]]
事實上元組的括號可以省略,即我們可以更簡潔地使用reshape:
A = np.arange(6).reshape(2, 3)
newshape 中的某一個分量可以為-1,reshape會根據其他分量自動推算:
A = np.arange(6).reshape(2, -1)
print(A)
# [[0 1 2]
# [3 4 5]]
若 newshape = -1,那么reshape會將其展平為一維陣列:
A = np.arange(6).reshape(6).reshape(-1)
print(A)
# [0 1 2 3 4 5]
1.2 np.ravel()
A = np.arange(8).reshape(2, 2, 2).ravel()
print(A)
# [0 1 2 3 4 5 6 7]
1.3 np.flatten()
A = np.arange(8).reshape(2, 2, 2).flatten()
print(A)
# [0 1 2 3 4 5 6 7]
可以看出flatten的效果和ravel一樣,那使用哪一個更好呢?
直接說答案:使用flatten更好,具體原因見博客,
二、(類)轉置操作
| 函式 | 作用 |
|---|---|
| ndarray.T | 轉置一個陣列,即反轉shape |
| np.swapaxes(a, axis1, axis2) | 交換陣列的兩個軸 |
| np.moveaxis(a, s, d) | s 和 d 是整數或整型串列;將索引為 s 的軸移動到索引 d 處 |
2.1 ndarray.T
A = np.arange(6).reshape(2, 3)
print(A)
print(A.T)
# [[0 1 2]
# [3 4 5]]
# [[0 3]
# [1 4]
# [2 5]]
但要注意,ndarray.T 無法轉置一維陣列:
A = np.arange(6)
print(A)
print(A.T)
# [0 1 2 3 4 5]
# [0 1 2 3 4 5]
那我們該如何轉置一維陣列呢?有以下幾種方法:
方法一:先轉換為二維陣列
將 ndarray 變成二維陣列再進行轉置:
A = np.arange(4)
A = np.array([A])
print(A.T)
# [[0]
# [1]
# [2]
# [3]]
當然也可以使用 np.transpose(),它與 ndarray.T 等價:
A = np.arange(4)
print(np.transpose([A]))
# [[0]
# [1]
# [2]
# [3]]
方法二:使用reshape函式
A = np.arange(4)
A = A.reshape(len(A), -1) # 第二個引數改為1也可以
print(A)
# [[0]
# [1]
# [2]
# [3]]
方法三:使用newaxis
我們在本系列的第一篇文章中提到了 np.newaxis,這里我們將進一步講解它的用法.
newaxis 的本質是 None:
print(np.newaxis == None)
# True
正如其名,將 newaxis 和 切片結合起來使用可以為陣列添加一個新的維度(軸),它能將一維陣列變為二維陣列,將二維陣列變為三維陣列,也可以直接將一維陣列變為三維陣列等,
巧記: newaxis 位于哪一軸,則得到的結果沿該軸的長度就為1
可能不太好理解,這里舉幾個例子,假設 A 是一個長度為3的一維陣列,則:
A[np.newaxis, :]: newaxis位于第一個軸,則得到的結果是一個 1 × 3 1\times 3 1×3 的陣列,A[:, np.newaxis]: newaxis位于第二個軸,則得到的結果是一個 3 × 1 3\times1 3×1 的陣列,A[:, np.newaxis, np.newaxis]: newaxis位于第二個軸和第三個軸,則得到的結果是一個 3 × 1 × 1 3\times1\times1 3×1×1 的陣列,
我們再舉幾個例子并結合shape方法來進一步說明 newaxis 的效果,
首先創建一個 3 × 4 3\times4 3×4 的陣列:
A = np.arange(12).reshape(3, 4)
print(A.shape)
# (3, 4)
然后使用 newaxis 添加新的軸:
print(A[:, :, np.newaxis].shape)
print(A[:, np.newaxis, :].shape)
print(A[np.newaxis, :, :].shape)
print(A[np.newaxis, np.newaxis, :, :].shape)
# (3, 4, 1)
# (3, 1, 4)
# (1, 3, 4)
# (1, 1, 3, 4)
看完這些例子,相信你對 newaxis 已經有了一個基本的認知,那如何轉置一個維陣列也不再是難事了,
因為轉置后的一維陣列一定是形如
a
×
1
a\times 1
a×1 的形狀,因此 newaxis 一定位于第二個軸,所以只需要 A[:, np.newaxis] 即可轉置:
A = np.arange(4)
print(A[:, np.newaxis])
# [[0]
# [1]
# [2]
# [3]]
2.2 np.swapaxes()
A = np.zeros((3, 4, 5))
print(A.shape)
# (3, 4, 5)
print(np.swapaxes(A, 0, 1).shape)
print(np.swapaxes(A, 0, 2).shape)
print(np.swapaxes(A, 1, 2).shape)
# (4, 3, 5)
# (5, 4, 3)
# (3, 5, 4)
2.3 np.moveaxis()
s 和 d 都為整數時:
A = np.zeros((3, 4, 5))
print(np.moveaxis(A, 0, 2).shape)
print(np.moveaxis(A, 0, -1).shape)
print(np.moveaxis(A, -1, -2).shape)
# (4, 5, 3)
# (4, 5, 3)
# (3, 5, 4)
s 和 d 都為整型串列時:
A = np.zeros((3, 4, 5))
print(np.moveaxis(A, [0, 1], [1, 2]).shape)
print(np.moveaxis(A, [0, 1], [0, 2]).shape)
print(np.moveaxis(A, [1, 0], [0, 2]).shape)
# (5, 3, 4)
# (3, 5, 4)
# (4, 5, 3)
三、合并陣列
| 函式 | 作用 |
|---|---|
| np.concatenate((a1, a2, …), axis=0) | a1, a2等是陣列,axis控制連接的方向;用于將多個陣列連接在一起,當axis為None時,會在連接之前壓平將要連接的各個陣列 |
| np.stack(arrays, axis=0) | arrays是由陣列組成的串列或元組;沿axis方向堆疊這些陣列 |
| np.block(arrays) | 將若干個陣列組合在一起構成一個新陣列;常用于構建分塊矩陣 |
| np.vstack((a1, a2, …)) | 垂直堆疊陣列 |
| np.hstack((a1, a2, …)) | 水平堆疊陣列 |
3.1 np.concatenate()
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6]])
print(np.concatenate((a, b), axis=0))
# [[1 2]
# [3 4]
# [5 6]]
print(np.concatenate((a, b.T), axis=1))
# [[1 2 5]
# [3 4 6]]
print(np.concatenate((a, b), axis=None))
# [1 2 3 4 5 6]
若要連接兩個一維陣列,只需要:
a = np.array([1, 2])
b = np.array([3, 4])
print(np.concatenate((a, b)))
# [1 2 3 4]
3.2 np.stack()
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(np.stack((a, b)))
# [[1 2 3]
# [4 5 6]]
print(np.stack((a, b), axis=1))
# [[1 4]
# [2 5]
# [3 6]]
arrays = [np.zeros((2, 3)) for _ in range(4)]
print(np.stack(arrays, axis=0).shape)
print(np.stack(arrays, axis=1).shape)
print(np.stack(arrays, axis=2).shape)
# (4, 2, 3)
# (2, 4, 3)
# (2, 3, 4)
注意到 axis=2 實際上就是最后一個軸,我們也可以用 axis=-1 來代替它,效果是一樣的,其他軸也可以此類推:
print(np.stack(arrays, axis=-3).shape)
print(np.stack(arrays, axis=-2).shape)
print(np.stack(arrays, axis=-1).shape)
# (4, 2, 3)
# (2, 4, 3)
# (2, 3, 4)
3.3 np.block()
A = np.eye(2) * 2
B = np.eye(3) * 3
C = np.block([
[A, np.zeros((2, 3))],
[np.ones((3, 2)), B ]
])
print(C)
# [[2. 0. 0. 0. 0.]
# [0. 2. 0. 0. 0.]
# [1. 1. 3. 0. 0.]
# [1. 1. 0. 3. 0.]
# [1. 1. 0. 0. 3.]]
3.3 np.vstack()
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(np.vstack((a, b)))
# [[1 2 3]
# [4 5 6]]
更形象的解釋:因為是垂直堆疊,所以把 B B B 放在 A A A 下面
A = [ 1 , 2 , 3 ] , B = [ 4 , 5 , 6 ] A=[1, 2, 3],\quad B=[4,5,6] A=[1,2,3],B=[4,5,6]
a = np.array([[1], [2], [3]])
b = np.array([[4], [5], [6]])
print(np.vstack((a, b)))
# [[1]
# [2]
# [3]
# [4]
# [5]
# [6]]
同理把 B B B 放在 A A A 下面
A = [ 1 2 3 ] , B = [ 4 5 6 ] A=\begin{bmatrix} 1 \\ 2\\ 3 \\ \end{bmatrix} ,\quad B=\begin{bmatrix} 4 \\ 5\\ 6 \\ \end{bmatrix} A=???123????,B=???456????
3.4 np.hstack()
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(np.hstack((a, b)))
# [1 2 3 4 5 6]
更形象的解釋:因為是水平堆疊,所以把 B B B 放在 A A A 右邊
A = [ 1 , 2 , 3 ] , B = [ 4 , 5 , 6 ] A=[1, 2, 3],\quad B=[4,5,6] A=[1,2,3],B=[4,5,6]
a = np.array([[1], [2], [3]])
b = np.array([[4], [5], [6]])
print(np.hstack((a, b)))
# [[1 4]
# [2 5]
# [3 6]]
同理把 B B B 放在 A A A 右邊
A = [ 1 2 3 ] , B = [ 4 5 6 ] A=\begin{bmatrix} 1 \\ 2\\ 3 \\ \end{bmatrix} ,\quad B=\begin{bmatrix} 4 \\ 5\\ 6 \\ \end{bmatrix} A=???123????,B=???456????
四、劃分陣列
| 函式 | 作用 |
|---|---|
| np.split(a, indices/sections) | 將陣列a劃分成一些子陣列并以串列形式回傳;sections是子陣列的數量,indices是索引串列;可以按照數量劃分也可以按照索引位置劃分 |
| np.array_split(a, indices/sections) | 與split的唯一區別在于,當選擇數量劃分時,不必要求每個子陣列的形狀相同 |
| np.vsplit(a, indices/sections) | 垂直劃分陣列 |
| np.hsplit(a, indices/sections) | 水平劃分陣列 |
4.1 np.split()
按照數量劃分,每個子陣列的形狀相同:
a = np.arange(9)
print(np.split(a, 3))
# [array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])]
print(np.split(a, 4))
# ValueError: array split does not result in an equal division
報錯的原因是因為你無法將長度為9的陣列四等分,
當然我們也可以按照索引進行劃分:
a = np.arange(9)
print(np.split(a, [2, 5]))
# [array([0, 1]), array([2, 3, 4]), array([5, 6, 7, 8])]
print(np.split(a, [1, 3, 5, 7]))
# [array([0]), array([1, 2]), array([3, 4]), array([5, 6]), array([7, 8])]
4.2 np.array_split()
a = np.arange(9)
print(np.array_split(a, 4))
# [array([0, 1, 2]), array([3, 4]), array([5, 6]), array([7, 8])]
4.3 np.vsplit()
按數量劃分:
a = np.arange(16).reshape(4, 4)
print(np.vsplit(a, 2))
# [array([[0, 1, 2, 3],
# [4, 5, 6, 7]]), array([[ 8, 9, 10, 11],
# [12, 13, 14, 15]])]
按索引劃分:
a = np.arange(16).reshape(4, 4)
print(np.vsplit(a, [1, 2]))
# [array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8, 9, 10, 11],
# [12, 13, 14, 15]])]
當陣列的維度大于等于3時,劃分方向仍沿第一個軸(行):
a = np.arange(8).reshape(2, 2, 2)
print(np.vsplit(a, 2))
# [array([[[0, 1],
# [2, 3]]]), array([[[4, 5],
# [6, 7]]])]
4.4 np.hsplit()
按數量劃分:
a = np.arange(16).reshape(4, 4)
print(np.hsplit(a, 2))
# [array([[ 0, 1],
# [ 4, 5],
# [ 8, 9],
# [12, 13]]), array([[ 2, 3],
# [ 6, 7],
# [10, 11],
# [14, 15]])]
按索引劃分:
a = np.arange(16).reshape(4, 4)
print(np.hsplit(a, [1, 2]))
# [array([[ 0],
# [ 4],
# [ 8],
# [12]]), array([[ 1],
# [ 5],
# [ 9],
# [13]]), array([[ 2, 3],
# [ 6, 7],
# [10, 11],
# [14, 15]])]
當陣列的維度大于等于3時,劃分方向仍沿第二個軸(列):
a = np.arange(8).reshape(2, 2, 2)
print(np.hsplit(a, 2))
# [array([[[0, 1]],
# [[4, 5]]]), array([[[2, 3]],
# [[6, 7]]])]
五、反轉陣列
| 函式 | 作用 |
|---|---|
| np.flip(a, axis=None) | 沿axis方向反轉陣列a;axis為整數或整型元組;當axis為None,會將陣列沿所有的軸進行反轉,當axis為元組時,會將陣列沿元組中提到的軸進行反轉 |
| np.fliplr(a) | 沿第二個軸(列方向)進行反轉 |
| np.flipud(a) | 沿第一個軸(行方向)進行反轉 |
5.1 np.flip()
先考慮一維陣列:
a = np.arange(6)
print(np.flip(a))
# [5 4 3 2 1 0]
對于二維陣列:
A = np.arange(8).reshape(2, 2, 2)
print(A)
# [[[0 1]
# [2 3]]
#
# [[4 5]
# [6 7]]]
print(np.flip(A, axis=0))
# [[[4 5]
# [6 7]]
#
# [[0 1]
# [2 3]]]
print(np.flip(A, axis=1))
# [[[2 3]
# [0 1]]
#
# [[6 7]
# [4 5]]]
print(np.flip(A, axis=2))
# [[[1 0]
# [3 2]]
#
# [[5 4]
# [7 6]]]
print(np.flip(A))
# [[[7 6]
# [5 4]]
#
# [[3 2]
# [1 0]]]
print(np.flip(A, axis=(0, 2)))
# [[[5 4]
# [7 6]]
#
# [[1 0]
# [3 2]]]
5.2 np.fliplr()
A = np.diag([1, 2, 3])
print(np.fliplr(A))
# [[0 0 1]
# [0 2 0]
# [3 0 0]]
5.3 np.flipud()
A = np.diag([1, 2, 3])
print(np.flipud(A))
# [[0 0 3]
# [0 2 0]
# [1 0 0]]
現在,我們可以對flip()函式作一個總結:
flip(a, 0)等價于flipud(a)flip(a, 1)等價于fliplr(a)flip(a, n)等價于a[..., ::-1, ...],其中::-1的索引為nflip(a)等價于a[::-1, ::-1, ..., ::-1],其中所有位置上均是::-1flip(a, (0, 1))等價于a[::-1, ::-1, ...],只有索引0和1處是::-1
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/423601.html
標籤:AI
