2014-05-02 110 views
39

我努力選擇numpy矩陣的每行特定列。我解決了以下問題的一個好辦法後我Numpy通過使用索引列表選擇每行的特定列索引

假設我有,我會叫X

[1, 2, 3] 
[4, 5, 6] 
[7, 8, 9] 

以下矩陣我也有按每一行,我會打電話ÿ列索引列表

[1, 0, 2] 

我需要得到

[2] 
[4] 
[9] 

而是用不知疲倦列表的值xes Y我也可以生成一個與X形狀相同的矩陣,其中每列都是一個bool /(int在0-1範圍內的值,表示這是否是必需的列。

[0, 1, 0] 
[1, 0, 0] 
[0, 0, 1] 

我知道這可以用迭代陣列上,選擇我需要的列值來完成,但我不知道是否有更好的解決方案。這將在大型數據陣列上頻繁執行,這就是爲什麼我必須儘可能快地運行。

謝謝

回答

46

如果你已經有了一個布爾數組,你可以以此爲基礎進行像這樣直接選擇:

>>> a = np.array([True, True, True, False, False]) 
>>> b = np.array([1,2,3,4,5]) 
>>> b[a] 
array([1, 2, 3]) 

當您最初的例子走,你可以做到以下幾點:

>>> a = np.array([[1,2,3], [4,5,6], [7,8,9]]) 
>>> b = np.array([[False,True,False],[True,False,False],[False,False,True]]) 
>>> a[b] 
array([2, 4, 9]) 

你也可以添加一個arange並對它做直接選擇,儘管取決於你如何生成你的布爾數組以及你的代碼看起來如何ke YMMV。

>>> a = np.array([[1,2,3], [4,5,6], [7,8,9]]) 
>>> a[np.arange(len(a)), [1,0,2]] 
array([2, 4, 9]) 

希望有幫助,讓我知道你是否有任何問題。

+4

使用'arange'的例子+1。這對於我從多個矩陣中檢索不同的塊特別有用(基本上這個例子的3D例子) – Griddo

+1

嗨,你能解釋爲什麼我們必須使用'arange'而不是':'?我知道你的方式有效,但我不明白爲什麼。 – marcotama

+0

@tamzord,因爲它是一個numpy數組而不是一個香草python列表,所以':'語法的工作方式不一樣。 –

1

您可以通過使用迭代器做到這一點。就像這樣:

np.fromiter((row[index] for row, index in zip(X, Y)), dtype=int) 

時間:

N = 1000 
X = np.zeros(shape=(N, N)) 
Y = np.arange(N) 

#@Aशwini चhaudhary 
%timeit X[np.arange(len(X)), Y] 
10000 loops, best of 3: 30.7 us per loop 

#mine 
%timeit np.fromiter((row[index] for row, index in zip(X, Y)), dtype=int) 
1000 loops, best of 3: 1.15 ms per loop 

#mine 
%timeit np.diag(X.T[Y]) 
10 loops, best of 3: 20.8 ms per loop 
+1

OP提到它應該在* large *陣列上快速運行,所以你的基準測試不是很有代表性。我很好奇你的最後一個方法是如何執行(很多)更大的數組的! –

+0

@moarningsun:已更新。 'np.diag(X.T [Y])'很慢...但是'np.diag(X.T)'很快(10us)。我不知道爲什麼。 –

1

作爲一個純粹的numpythonic方法,你可以從第二軸指數使用np.take(),則對角線的結果將是你期望的輸出:

np.diagonal(np.take(arr, idx, axis=1)) 

演示:

>>> arr = np.array([[1, 2, 3], 
... [4, 5, 6], 
... [7, 8, 9]]) 
>>> 
>>> idx = [1, 0, 2] 
>>> 
>>> np.diagonal(np.take(arr, idx, axis=1)) 
array([2, 4, 9]) 
+1

可以說這不是numpythonic,因爲它會隨着更大的陣列而變得可怕,並且具有更大的內存成本。 – miradulo