np.stack/hstack/vstack函數解析

在Python中,經常會用到關於數組的堆疊,如np.stack函數就是一個用於numpy數組堆疊的函數,關於該函數的用法,大都是給出了示例,而沒有分析其中原理,下面會舉例關於np.stack函數的用法,示例和原理。

np.stack函數的調用方式:
stack(arrays, axis=0),arrays可以傳數組和列表。

import numpy as np
# np.stack(arrays,axis)

下面給出一個具體的示例如下:

import numpy as np
# np.stack(arrays,axis)
a = np.array([[1,2,3,4], [5,6,7,8]])
b = np.array([[2,2,1,4], [3,5,7,8]])
c = np.array([[5,7,7,3], [6,6,2,8]])
arrays = np.asarray([a, b, c])
print("\narrays.shape" + str(arrays.shape))
print(arrays)

s0 = np.stack(arrays, axis=0)
print("\ns0.shape"+ str(s0.shape))
print(s0)
s1 = np.stack(arrays, axis=1)
print("\ns1.shape"+ str(s1.shape))
print(s1)
s2 = np.stack(arrays, axis=2)
print("\ns2.shape"+ str(s2.shape))
print(s2)

輸出結果:

arrays.shape(3, 2, 4)
[[[1 2 3 4]
  [5 6 7 8]]

 [[2 2 1 4]
  [3 5 7 8]]

 [[5 7 7 3]
  [6 6 2 8]]]

s0.shape(3, 2, 4)
[[[1 2 3 4]
  [5 6 7 8]]

 [[2 2 1 4]
  [3 5 7 8]]

 [[5 7 7 3]
  [6 6 2 8]]]

s1.shape(2, 3, 4)
[[[1 2 3 4]
  [2 2 1 4]
  [5 7 7 3]]

 [[5 6 7 8]
  [3 5 7 8]
  [6 6 2 8]]]

s2.shape(2, 4, 3)
[[[1 2 5]
  [2 2 7]
  [3 1 7]
  [4 4 3]]

 [[5 3 6]
  [6 5 6]
  [7 7 2]
  [8 8 8]]]

例2:

import numpy as np
a=[[1,2,3],
   [4,5,6]]
print("列表a如下:")
print(a)

print("增加一維,新維度的下標爲0")
c=np.stack(a,axis=0)
print(c)

print("增加一維,新維度的下標爲1")
c=np.stack(a,axis=1)
print(c)

輸出:
列表a如下:
[[1, 2, 3], [4, 5, 6]]
增加一維,新維度下標爲0
[[1 2 3]
 [4 5 6]]
增加一維,新維度下標爲1
[[1 4]
 [2 5]
 [3 6]]

首先這裏arrays我傳的是一個列表,現在我開始講解這個stack()函數的意思,它就是對arrays裏面的每個元素(可能是個列表,元組,或者是個numpy的數組)變成numpy的數組後,再對每個元素增加一維(至於維度加在哪裏,是靠axis控制的),然後再把這些元素串起來(至於怎麼串,我下面會說)。

arrays裏面的每個元素必須形狀是一樣的,例如本例中列表a中的兩個元素[1,2,3]和[4,5,6]的形狀是一樣的,如果把[4,5,6]換成[4,5] ,那麼程序會報錯!而axis代表的是在哪個維度上加一維,例如axis=0(它是默認的)代表的就是增加的這一維的下標爲0,axis等於多少不是隨便亂寫的,如果參數arrays裏面的每個元素是個1維的,那麼調用stack()函數增加一維後會變成2維的,所以axis只能等於0和1(維度的下標是從0開始的),而參數axis=0和axis=1得到的結果是不一樣的。

例如上面的代碼中a列表中的第一個元素爲[1,2,3],那麼當axis=0的時候,就是在它的中括號外面再加一箇中括號,變成[ [1,2,3] ](其實1,2,3之間是沒有逗號的,因爲stack()函數會先把參數arrays中的每個元素變成numpy的數組,數組之間是沒有逗號的,看看上面的代碼輸出就知道了,這裏大家明白就行,我爲了方便講解,下面還會加上逗號),這樣最外面那層中括號才代表維度下標爲0的那維;當axis=1的時候,就是在裏面加個中括號,變成了[ [1],[2],[3] ],這樣裏面加的那層中括號才代表維度下標爲1的那維。同理當axis=0的時候[4,5,6]變成[ [ 4,5,6] ],當axis=1的時候,變成[ [4],[5],[6] ]。下面我們講如何把增加一維度後的每個元素串起來。

怎麼把上面那兩個元素增加維度後的結果串起來呢,其實很簡單。現在我們已經知道了增加維度無非是增加中括號的意思,至於在哪裏加中括號,取決於axis等於幾。我們把增加的中括號想像成一個個的箱子。還拿上面的代碼來說,當axis=0的時候,我們把套在[1,2,3]外面的中括號(就是[ [1,2,3] ]最外層的那個中括號)看做是箱子A,這個箱子A也會套在[4,5,6]的外面,所以我們就先把[1,2,3]和[4,5,6]放在一起,變成[1,2,3],[4,5,6],然後再一起套上箱子A,變成[ [1,2,3],[4,5,6] ]這就是當axis=0的時候程序的輸出結果。

現在再來看當axis=1的時候,對於[1,2,3],我們把套在1外面的箱子(就是上面講的[ [1],[2],[3] ]中1外面的那層中括號)看做A,套在2外面的看做B,套在3外面的看做C,同理,箱子A也會套在4的外面,箱子B也會套在5的外面,箱子C也會套在6的外面。那麼我們就把1和4放一起,2和5放一起,3和6放一起,變成[ 1,4 ,2,5 ,3,6 ]然後把箱子A,B,C分別套在1,4 , 2,5 , 3,6的外面,變成[ [1,4] , [2,5] , [3,6] ]這就是程序中axis=1的時候程序的輸出結果。

大家發現了沒有,串起來的時候其實就是把arrays中每個元素在相同的位置套箱子的一些小塊(這裏叫小塊這個名詞可能不洽當,但是大家明白就行)放在一起後,再套箱子,就是外面套個中括號,這就是堆疊。

鞏固1:

import numpy as np
a=[1,2,3,4]
b=[5,6,7,8]
c=[9,10,11,12]
print("a=",a)
print("b=",b)
print("c=",c)

print("增加一維,新維度的下標爲0")
d=np.stack((a,b,c),axis=0)
print(d)

print("增加一維,新維度的下標爲1")
d=np.stack((a,b,c),axis=1)
print(d)

輸出:
('a=', [1, 2, 3, 4])
('b=', [5, 6, 7, 8])
('c=', [9, 10, 11, 12])
增加一維,新維度的下標爲0
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
增加一維,新維度的下標爲1
[[ 1  5  9]
 [ 2  6 10]
 [ 3  7 11]
 [ 4  8 12]]

鞏固2:

import numpy as np
a=[[1,2,3],
   [4,5,6]]
b=[[1,2,3],
   [4,5,6]]
c=[[1,2,3],
   [4,5,6]]
print("a=",a)
print("b=",b)
print("c=",c)

print("增加一維,新維度的下標爲0")
d=np.stack((a,b,c),axis=0)
print(d)

print("增加一維,新維度的下標爲1")
d=np.stack((a,b,c),axis=1)
print(d)
print("增加一維,新維度的下標爲2")
d=np.stack((a,b,c),axis=2)
print(d)

輸出:
('a=', [[1, 2, 3], [4, 5, 6]])
('b=', [[1, 2, 3], [4, 5, 6]])
('c=', [[1, 2, 3], [4, 5, 6]])
增加一維,新維度的下標爲0
[[[1 2 3]
  [4 5 6]]

 [[1 2 3]
  [4 5 6]]

 [[1 2 3]
  [4 5 6]]]
增加一維,新維度的下標爲1
[[[1 2 3]
  [1 2 3]
  [1 2 3]]

 [[4 5 6]
  [4 5 6]
  [4 5 6]]]
增加一維,新維度的下標爲2
[[[1 1 1]
  [2 2 2]
  [3 3 3]]

 [[4 4 4]
  [5 5 5]
  [6 6 6]]]

當axis=0的時候,列表a,b,c最外面都需要套箱子(就是加中括號),那麼我把你們先放一起,變成下面這樣

[[1,2,3],[4,5,6]],
[[1,2,3],[4,5,6]],
[[1,2,3],[4,5,6]]

然後在最外面套箱子,變成

[
[[1,2,3],[4,5,6]],
[[1,2,3],[4,5,6]],
[[1,2,3],[4,5,6]]
]

當axis=1的時候,列表a,b,c中的[1,2,3]需要套同樣的箱子,列表a,b,c中的[4,5,6]需要套同樣的箱子,好,我先把你們放一塊變成下面這樣

[
    [1,2,3],[1,2,3],[1,2,3]
    ,
    [4,5,6],[4,5,6],[4,5,6]

]

然後開始分別在 [1,2,3],[1,2,3],[1,2,3]的外面和[4,5,6],[4,5,6],[4,5,6]的外面套箱子,變成下面這樣

[
    [[1,2,3],[1,2,3],[1,2,3]]
    ,
    [[4,5,6],[4,5,6],[4,5,6]]

]

當axis=2的時候,列表a,b,c中的1,2,3,4,5,6都需要套箱子,我把你們先放一起變成:

[
    [1,1,1  ,  2,2,2  , 3,3,3],
    [4,4,4  ,  5,5,5  , 6,6,6]
]

然後在1,1,1 ………6,6,6的外面分別套箱子變成:

[
    [[1,1,1]  ,  [2,2,2]  , [3,3,3]],
    [[4,4,4]  ,  [5,5,5]  , [6,6,6]]
]

2. hstack()函數
函數原型:hstack(tup) ,參數tup可以是元組,列表,或者numpy數組,返回結果爲numpy的數組。看下面的代碼體會它的含義

import numpy as np
a=[1,2,3]
b=[4,5,6]
print(np.hstack((a,b)))

輸出:[1 2 3 4 5 6 ]
import numpy as np
a=[[1],[2],[3]]
b=[[1],[2],[3]]
c=[[1],[2],[3]]
d=[[1],[2],[3]]
print(np.hstack((a,b,c,d)))

輸出:
[[1 1 1 1]
 [2 2 2 2]
 [3 3 3 3]]

它其實就是水平(按列順序)把數組給堆疊起來,vstack()函數正好和它相反。

3. vstack()函數
函數原型:vstack(tup) ,參數tup可以是元組,列表,或者numpy數組,返回結果爲numpy的數組。看下面的代碼體會它的含義

import numpy as np
a=[1,2,3]
b=[4,5,6]
print(np.vstack((a,b)))

輸出:
[[1 2 3]
 [4 5 6]]
import numpy as np
a=[[1],[2],[3]]
b=[[1],[2],[3]]
c=[[1],[2],[3]]
d=[[1],[2],[3]]
print(np.vstack((a,b,c,d)))

輸出:
[[1]
 [2]
 [3]
 [1]
 [2]
 [3]
 [1]
 [2]
 [3]
 [1]
 [2]
 [3]]

它是垂直(按照行順序)的把數組給堆疊起來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章