2014-06-26 17 views
2

我在使用NumPy時遇到的一個重複性錯誤是,嘗試索引數組失敗,因爲數組的維度之一是單例,因此該維度已被清除,被索引。這在設計用於對任意大小的數組進行操作的函數中尤其成問題。我正在尋找最便宜,最普遍的方法來避免這種錯誤。處理python數組中的維度崩潰

下面是一個例子:

import numpy as np 
f = (lambda t, u, i=0: t[:,i]*u[::-1]) 
a = np.eye(3) 
b = np.array([1,2,3]) 
f(a,b) 
f(a[:,0],b[1]) 

第一個電話按預期工作。第二次調用失敗的方式有兩種:1)t不能被[:,0]索引,因爲它的形狀爲(3,),並且2)u根本不能被索引,因爲它是一個標量。

下面是發生在我身上的修復:

1)使用np.atleast_1dnp.atleast_2d等(可能用條件,以確保尺寸是按照正確的順序)內f,以確保所有參數都他們需要的尺寸。這排除了lambda的使用,並且可以採用我不想要的幾條線。

2)而不是上面寫f(a[:,0],b[1]),使用f(a[:,[0]],b[[1]])。這很好,但我總是必須記住放入額外的括號中,如果索引存儲在一個變量中,您可能不知道是否應該放入額外的括號。例如: -

idx = 1 
f(a[:,[0]],b[[idx]]) 
idx = [2,0,1] 
f(a[:,[0]],b[idx]) 

在這種情況下,你似乎不得不呼籲idxnp.atleast_1d第一,這可能比把np.atleast_1d在功能上更加繁瑣。

3)在某些情況下,我可以擺脫只是不放入索引。例如:

f = lambda t, u: t[0]*u 
f(a,b) 
f(a[:,0],b[0]) 

這是有效的,當它適用時顯然是最光滑的解決方案。但是在任何情況下都沒有幫助(特別是,您的維度必須以正確的順序開始)。

那麼,有沒有比上述更好的方法?

+0

許多numpy函數都有很多python代碼行,它們在執行中央操作之前對輸入進行重塑和按摩。看看'atleast_1d'的功能(10行)。 – hpaulj

+0

我感到你的痛苦。下面是我通常如何處理這個問題:首先,我存儲輸入形狀,並檢查輸入是否是標量,然後我應用'np.atleast_1d'這樣的函數進行計算,最後重新調整結果以匹配輸入形狀(例如變回標量)。下行:這是很多樣板。上行:更靈活的接口,並且對於呼叫者而言更少意外。我認爲這是一個相當普遍的功能,它是你的域特定庫的一部分。 – Lemming

回答

1

有很多方法可以避免這種行爲。

首先,當你索引的np.ndarrayslice,而不是一個整數的尺寸,輸出的維數將是相同的輸入:

import numpy as np 

x = np.arange(12).reshape(3, 4) 
print x[:, 0].shape    # integer indexing 
# (3,) 

print x[:, 0:1].shape    # slice 
# (3, 1) 

這是我的避免該問題的首選方式,因爲它可以非常容易地從單元素到多元素的選擇(例如x[:, i:i+1] vs x[:, i:i+n])進行概括。

正如你已經提到了,你也可避免使用任何整數序列索引到一個維維損失:

print x[:, [0]].shape    # list 
# (3, 1) 

print x[:, (0,)].shape   # tuple 
# (3, 1) 

print x[:, np.array((0,))].shape # array 
# (3, 1) 

如果你選擇堅持使用整數索引,可以隨時插入使用np.newaxis(或相當於None)的新單維度:

print x[:, 0][:, np.newaxis] 
# (3, 1) 

print x[:, 0][:, None] 
# (3, 1) 

否則,你可以手動將其重塑正確的尺寸(這裏使用-1來推斷第一維部門自動化的大小凱莉):

print x[:, 0].reshape(-1, 1).shape 
# (3, 1) 

最後,你可以使用一個np.matrix而非np.ndarraynp.matrix行爲更像一個MATLAB矩陣,其中單尺寸被留在每當你索引與一個整數:

y = np.matrix(x) 
print y[:, 0].shape 
# (3, 1) 

然而,應注意的是有和np.ndarray一個number of other important differences之間np.matrix,例如*操作者進行數組上的元素相乘,但矩陣上的矩陣相乘。在大多數情況下,最好堅持np.ndarrays