增加或減少 Numpy 數組維度


 
 

在 Numpy 的使用過程中,我們常常需要從原數組中提取部分信息或將原數組拼湊成一個高維的數組,這些操作根本上來說都是希望基於原數組得到一個維度不同的數組。 下面對一些常用方法進行總結。

降低維度

比如我們希望從一個二維數組中抽出某些列,可以這樣:

In [45]:
a = np.arange(12).reshape(4,3) a 
Out[45]:
array([[ 0, 1, 2],
 [ 3, 4, 5],
 [ 6, 7, 8],
 [ 9, 10, 11]])
In [46]:
b = np.array([True, False, True, False]) a[b,:] 
Out[46]:
array([[0, 1, 2],
 [6, 7, 8]])
 

利用 ndarray 的 broadcasting 機制,我們可以直接寫成

In [47]:
a[b] 
Out[47]:
array([[0, 1, 2],
 [6, 7, 8]])
 

b 也可以不用與第一維的長度匹配,缺失部分默認為 False

In [48]:
b = np.array([True, False, True]) a[b,:] 
Out[48]:
array([[0, 1, 2],
 [6, 7, 8]])
 

需要注意的是 b 必須也是一個 ndarray,否則 numpy 不會將其當作一個 mask 數組,而是當作 index 數組,比如

In [49]:
b = [True, False, True, False] a[b], a[b,:] 
Out[49]:
(array([[3, 4, 5],
 [0, 1, 2],
 [3, 4, 5],
 [0, 1, 2]]),
 array([[3, 4, 5],
 [0, 1, 2],
 [3, 4, 5],
 [0, 1, 2]]))
 

上例中 numpy 將 True 和 False 直接當作 1 和 0 來處理。其實用 index 數組同樣可達到 mask 數組的效果

In [50]:
b = [0, 2] a[b,:] 
Out[50]:
array([[0, 1, 2],
 [6, 7, 8]])
 

總結一下,只有布爾型的 ndarray 才能當作 mask 數組提取數值。下面列舉一些高維的例子:

In [51]:
a = np.arange(16).reshape((2,2,4)) a 
Out[51]:
array([[[ 0, 1, 2, 3],
 [ 4, 5, 6, 7]],

 [[ 8, 9, 10, 11],
 [12, 13, 14, 15]]])
In [52]:
b = np.array([[True, False], [True, False]]) a[b,:] 
Out[52]:
array([[ 0, 1, 2, 3],
 [ 8, 9, 10, 11]])
 

這等價於在前兩維指定坐標

In [53]:
a[[0,1], [0, 0], :] 
Out[53]:
array([[ 0, 1, 2, 3],
 [ 8, 9, 10, 11]])
In [54]:
a[b.nonzero()] 
Out[54]:
array([[ 0, 1, 2, 3],
 [ 8, 9, 10, 11]])
 

增加維度

有兩種常用方法可以用於增加數組維度,一是使用 index 數組(必須是 ndarray 類型),二是借助 newaxis,這里只討論第二種方法,因為其簡單直觀。

 

比如我們希望將兩個二維數組在一個新的維度上拼接成一個三維數組,我們可以先利用 newaxis 構建出這個維度,然后再使用 concatenatevstack, hstack 等方法。

In [55]:
a = np.array([[1,2],[3,4]]) b = np.array([[5,6],[7,8]]) a_ = a[..., np.newaxis] b_ = b[..., np.newaxis] c = np.concatenate((a_, b_), 2) c 
Out[55]:
array([[[1, 5],
 [2, 6]],

 [[3, 7],
 [4, 8]]])
 

注意concatenate vstack hstack 等方法並不能修改數組本身的維度。

 

假設我們想要在第一維之前插入新維度,可以更簡單地寫成:

In [56]:
c = np.array([a, b]) c 
Out[56]:
array([[[1, 2],
 [3, 4]],

 [[5, 6],
 [7, 8]]])
 

當然如果覺得 newaxis 麻煩,可以先用上面的方法增加新維度,然后再將其從第一維移至想要的位置:

In [57]:
np.rollaxis(c,0,3) 
Out[57]:
array([[[1, 5],
 [2, 6]],

 [[3, 7],
 [4, 8]]])
 

注意np.rollaxis 這個函數設計得極其糟糕,它的第二個參數為需要調整位置的軸,第三個參數為目標位置。如果當前位置等於目標位置,函數不作任何操作,否則當前軸將被調整至緊鄰目標位置的前一位置處,np.rollaxis(x,n,n+1) 都是沒有實際效果的寫法。

 

總結

  • 減少維度主要通過在數組的某些維度中選取符合條件的元素,具體可采用 index 或 mask 數組。
  • 增加維度主要通過 np.newaxis 或直接構建新數組並結合 rollaxis
  • rollaxis sucks

This web site does not host notebooks, it only renders notebooks available on other websites.

Delivered by Fastly, Rendered by Rackspace

nbviewer GitHub repository.

nbviewer version: f399a06

IPython version: 3.2.0-dev ( 5e57377 )

Rendered 7 minutes ago


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM