2014-10-01 59 views
2

我具有相同的高度的2D numpy的陣列而不是寬度的列表:列表解析式的方法具有多於一個維度

list_of_arrays = [np.random.rand(3,4),np.random.rand(3,5),np.random.rand(3,6)] 

我想建立一個新的數組,其中各列是我列表中的數組的隨機列。我可以用for循環來做到這一點,例如:

new_array = np.zeros((3,3)) 
for x in range(3): 
    new_array[:,x] = list_of_arrays[x][:,random.randint(0,list_of_arrays[x].shape[1])] 

這對我來說並不乾淨。我想用類似列表理解的方法,例如

new_array = [list_of_arrays[x][:,random.randint(0,list_of_arrays[x].shape[1])] for x in range(3)] 

這顯然返回一個列表,而不是根據需要返回一個數組。我可以將列表轉換爲一個數組,但增加了一個無關的中間值。有沒有簡單的方法來做到這一點?類似的問題,我已經看到使用1d數組使用numpy.fromiter,但不會在2維工作。

如果有人想提出完全不同的/更清潔/更有效的方法來解決這個問題,那也是值得讚賞的。

+2

在'np.array'中包裝列表沒什麼問題。 'numpy'一直都是這樣。 – hpaulj 2014-10-01 22:59:52

回答

2

你可以讓你的列表中理解簡單的是通過遍歷數組,而不是指數結束了,

new_array = np.array([x[:,np.random.randint(0, x.shape[1])] for x in list_of_arrays]).T 

In [32]: %timeit np.array([x[:,np.random.randint(0, x.shape[1])] for x in a]).T 
100000 loops, best of 3: 10.2 us per loop 

轉置(.T)是因爲遍歷數組會產生行,因此通過arr.T重複產生th e欄。同樣,在構建數組時,每個元素都被視爲一個行,所以在構建之後,我們需要對其進行轉置,以便將供給數組構造的列表轉換爲列。

如果導入標準random模塊,你可以做

new_array = np.array([random.choice(x.T) for x in list_of_arrays]).T 

In [36]: %timeit np.array([random.choice(x.T) for x in a]).T 
100000 loops, best of 3: 9.18 us per loop 

這是稍快。

+0

使用遍歷數組並使用'random.choice'絕對是很好的改進 - 感謝這些提示。但是,如果我沒有弄錯,這是生成一個列的列表,然後將其轉換爲一個ndarray。如果可能的話,我想在這裏刪掉中間人,可以這麼說。 – Joe 2014-10-01 20:03:26

+1

@Joe,你從一個'list'開始,所以在某些時候你調用'np.ndarray',不管你是否用'np。* stack'或'np.zeros'來掩飾它。 – wflynny 2014-10-01 20:24:04

+0

我希望避免的是生成第二個列表來保存從第一個列表中拉出的數組片 - 我希望通過將這些數組直接插入數組來加快速度。然而,考慮到內存分配給數組的方式和上面的@ hpaulj的評論的進一步研究,似乎中間列表實際上很重要。因此,我將使用此代碼並查看腳本中其他位置的性能提升。謝謝! – Joe 2014-10-02 18:01:08

0

你可以將數組組合到另一個數組而不是列表中嗎?

>>> b= np.hstack((np.random.rand(3,4),np.random.rand(3,5),np.random.rand(3,6))) 
>>> b.shape 
(3, 15) 

然後你可以使用broadcasting,而不是列表解析,挑選隨機列:

new_array=b[:,np.random.randint(0,b.shape[1],3)] 
+0

這裏的問題是,我需要每個初始數組中的一列,而不是任何三列,這就是您的方法看起來像它產生的。我可以讓代碼記住哪個「block」對應於哪個初始數組,但是假設我可以有任意數量的數組,每個數組都有可能變得複雜的很多列。 – Joe 2014-10-01 18:05:32

相關問題