2011-01-27 118 views
15

我真的很困惑numpy數組的索引邏輯與幾個維度。下面是一個例子:numpy數組中的索引混淆

import numpy as np 
A = np.arange(18).reshape(3,2,3) 
[[[ 0, 1, 2], 
    [ 3, 4, 5]], 

[[ 6, 7, 8], 
    [ 9, 10, 11]], 

[[12, 13, 14], 
    [15, 16, 17]]]) 

這給了我的形狀(3,2,3)的陣列,稱它們爲(X,Y,Z)爲自變量的緣故。現在我想要一個數組B,其中A的元素對應於x = 0,2 y = 0,1和z = 1,2。像

array([[[ 1, 2], 
     [4, 5]], 

     [[13, 14], 
     [16, 17]]]) 

我天真地以爲

B=A[[0,2],[0,1],[1,2]] 

會做這項工作。但它給出

array([ 2, 104]) 

並且不起作用。

A[[0,2],:,:][:,:,[1,2]] 

完成這項工作。但我仍然想知道我的第一次嘗試有什麼問題。什麼是做我想做的最好的方式?

+0

我的個人看法:你的方式觸發了Numpy的高級索引。在高級索引上下文中,A [[0,2],[0,1],[1,2]]被解釋爲「在每個維度中選擇每個索引編號(有點貪婪的方法) – 2017-10-17 15:02:34

回答

17

在NumPy basicadvanced中有兩種類型的索引。基本索引使用片元組進行索引,並且不復制數組,而是creates a view with adjusted strides。相比之下,高級索引也使用列表或索引數組並複製數組。

你的第一次嘗試

B = A[[0, 2], [0, 1], [1, 2]] 

採用先進的索引。在高級索引中,所有索引列表都是第一個broadcasted,形狀相同,並且此形狀用於輸出數組。在這種情況下,他們已經相同的形狀,所以廣播不做任何事情。輸出數組也將具有這種形式的兩個條目。輸出數組的第一個條目是通過使用三個列表的所有第一指數獲得,第二通過使用所有第2指標:

B = numpy.array([A[0, 0, 1], A[2, 1, 2]]) 

你的第二個方法

B = A[[0,2],:,:][:,:,[1,2]] 

的工作,但它效率低下。它使用兩次高級索引,因此您的數據將被複制兩次。

要得到你真正想要擁有先進的索引,您可以使用

A[np.ix_([0,2],[0,1],[1,2])] 

nikow指出的是什麼。這將只複製一次數據。

在你的榜樣,你能逃脫沒有在所有複製數據,只使用基本的索引:

B = A[::2, :, 1:2] 
+0

謝謝Sven,但是有沒有比使用高級索引更好的方法來從數組中提取不連續(或者有規律間隔)的索引(我的例子太簡單了,因爲所有的im提取的索引是連續的間隔的) – jonalm 2011-01-27 14:16:37

7

我推薦以下高級教程,這也解釋了各種索引方法:NumPy MedKit

一旦你理解了有效的方法來索引數組(以及它們如何組合使用)它纔有意義。如果你的第一次嘗試是有效的,那麼這將與其他一些索引技術相沖突(減少你在其他用例中的選項)。

在您的例子,你可以利用第三指數涵蓋連續範圍:

A[[0,2],:,1:] 

你也可以使用

A[np.ix_([0,2],[0,1],[1,2])] 

這是在更一般的情況下,當後者指數都得心應手不連續。 np.ix_只是構造三個索引數組。

正如Sven在他的回答中指出的那樣,在這種特定情況下(使用視圖而不是複製版本)有更有效的方法。

編輯:正如Sven所指出的,我的答案包含一些我已經刪除的錯誤。我仍然認爲他的回答比較好,但不幸的是我現在不能刪除我的。

+0

Some note:1 。你的前兩個代碼片段不是等價的 - 它們產生不同形狀的數組。第一行是** not **像第二個那樣解釋。2. jonalm的解決方案並不可取,因爲它複製了兩次數組。在另一個答案中多解釋一下這些問題 – 2011-01-27 13:49:01

0
A[(0,2),:,1:] 

如果你想

array([[[ 1, 2], 
     [ 4, 5]], 

     [[13, 14], 
     [16, 17]]]) 

你想要[索引,你想要的排,你想要的排列]