如果你有幾個 NumPy 陣列,可能會想要對它們進行串接、堆疊、拆開等,這類動作是蠻常見的需求,只不過因為 NumPy 陣列有軸的觀念,讓這類動作可以有更豐富的處理方式。
例如,對於一維陣列,串接的結果很簡單就能想像:
>>> import numpy as np
>>> a = np.array([1, 2, 3])
>>> b = np.array([4, 5, 6])
>>> np.concatenate([a, b])
array([1, 2, 3, 4, 5, 6])
>>>
concatenate
可以用來串接 NumPy 陣列,要被串接的陣列得放在一個清單裡頭,如果是多維陣列,預設是將軸 0 方向上的每個元素串接起來,可以透過 axis
來指定軸:
>>> c = np.array([[10, 20, 30], [40, 50, 60]])
>>> d = np.array([[100, 200, 300], [400, 500, 600]])
>>> np.concatenate([c, d])
array([[ 10, 20, 30],
[ 40, 50, 60],
[100, 200, 300],
[400, 500, 600]])
>>> np.concatenate([c, d], axis = 0)
array([[ 10, 20, 30],
[ 40, 50, 60],
[100, 200, 300],
[400, 500, 600]])
>>> np.concatenate([c, d], axis = 1)
array([[ 10, 20, 30, 100, 200, 300],
[ 40, 50, 60, 400, 500, 600]])
>>>
除了串接之外,還可以對陣列進行堆疊,例如垂直堆疊:
>>> a = np.array([1, 2, 3])
>>> b = np.array([4, 5, 6])
>>> np.vstack([a, b])
array([[1, 2, 3],
[4, 5, 6]])
>>> c = np.array([
... [7, 8, 9],
... [10, 11, 12]
... ])
>>> np.vstack([a, b, c])
array([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12]])
>>>
vstack
用來對陣列進行垂直堆疊,更精確的說法是,在軸 0 的方向進行堆疊;也可以使用 hstack
針對軸 1 的方向,也就是水平堆疊:
>>> c = np.array([
... [1, 2, 3],
... [4, 5, 6]
... ])
>>> d = np.array([
... [7, 8, 9],
... [10, 11, 12]
... ])
>>> c = np.array([
... [1, 2, 3],
... [4, 5, 6]
... ])
>>> d = np.array([
... [8],
... [9]
... ])
>>> np.hstack([c, d])
array([[1, 2, 3, 8],
[4, 5, 6, 9]])
>>>
想針對軸 2 的方向,也就是以深度來堆疊的話,就使用 dstack
,這或許是最常使用的堆疊,例如:
>>> x = np.array([10, 20, 30])
>>> y = np.array([40, 50, 60])
>>> np.dstack([x, y])
array([[[10, 40],
[20, 50],
[30, 60]]])
>>>
為什麼說是最常使用的堆疊呢?以二維繪圖為例,經常地,你會需要將 x 軸的資料與 y 軸的資料組合為座標,這時就可以如上組合,如果想取得座標清單,取結果的索引 0 就可以了:
>>> coord = np.dstack([x, y])[0]
>>> coord
array([[10, 40],
[20, 50],
[30, 60]])
>>>
這個作法並不限於座標,在更高的維度,也可以用來取得向量清單:
>>> x0 = np.array([1, 2, 3])
>>> x1 = np.array([10, 20, 30])
>>> x2 = np.array([100, 200, 300])
>>> x3 = np.array([1000, 2000, 3000])
>>> v = np.dstack([x0, x1, x2, x3])
>>> v
array([[[ 1, 10, 100, 1000],
[ 2, 20, 200, 2000],
[ 3, 30, 300, 3000]]])
>>> v[0]
array([[ 1, 10, 100, 1000],
[ 2, 20, 200, 2000],
[ 3, 30, 300, 3000]])
>>>
串接與堆疊都是在組合陣列,相對地,也有可以分離陣列的函式。嗯?透過陣列索引不就可以嗎?是沒錯,不過有時,我想會想要指定索引,一次分離出數個陣列。例如:
>>> a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a1, a2 = np.split(a, [3])
>>> a1, a2
(array([1, 2, 3]), array([4, 5, 6, 7, 8, 9]))
>>> a1, a2, a3 = np.split(a, [3, 8])
>>> a1, a2, a3
(array([1, 2, 3]), array([4, 5, 6, 7, 8]), array([9]))
>>>
split
也可以指定 axis
:
>>> a = np.array([[1, 2, 3, 4], [6, 7, 8, 9]])
>>> a1, a2 = np.split(a, [2], axis = 1)
>>> a1
array([[1, 2],
[6, 7]])
>>> a2
array([[3, 4],
[8, 9]])
>>>
類似地,在分離時,也可以直覺地用垂直、水平或深度,對應的函式分別是 vsplit
、hsplit
與 dsplit
,例如垂直分離:
>>> a = np.arange(16).reshape((4, 4))
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
>>> a1, a2 = np.split(a, [2])
>>> a1
array([[0, 1, 2, 3],
[4, 5, 6, 7]])
>>> a2
array([[ 8, 9, 10, 11],
[12, 13, 14, 15]])
>>>