創建對應於行索引指數的2D網格:idxs[i1, i0]
並使用N x 1
陣列列索引。當像這樣索引到array
時,列索引將是broadcasted
到行索引的形狀。因此,我們將有一個broadcasted indexing
爲基礎的方法,像這樣 -
# Get 2D grid of row indices corresponding to two nested loops
row_idx = idxs[np.arange(array.shape[1])[:,None],np.arange(idxs.shape[1])]
# Use column indices alongwith row_idx to index into array.
# The column indices would be broadcasted when put as Nx1 array.
result = array[row_idx,np.arange(array.shape[1])[:,None]].T
請注意,在通過@ali_m的評論中提到,np.ix_
還可以用來創建row_idx
,像這樣 -
row_idx = idxs[np.ix_(np.arange(array.shape[1]),np.arange(idxs.shape[1]))]
運行測試和驗證輸出
功能定義:
def broadcasted_indexing(array,idxs):
row_idx = idxs[np.arange(array.shape[1])[:,None],np.arange(idxs.shape[1])]
return array[row_idx,np.arange(array.shape[1])[:,None]].T
def forloop(array,idxs):
result = np.zeros((idxs.shape[1],array.shape[1]))
for i0 in range(idxs.shape[1]):
for i1 in range(array.shape[1]):
result[i0, i1] = array[idxs[i1, i0], i1]
return result
運行測試和驗證輸出:
In [149]: # Inputs
...: m = 500
...: n = 400
...: array = np.random.rand(m,n)
...: idxs = np.random.randint(0,array.shape[1],(n,m))
...:
In [150]: np.allclose(broadcasted_indexing(array,idxs),forloop(array,idxs))
Out[150]: True
In [151]: %timeit forloop(array,idxs)
10 loops, best of 3: 136 ms per loop
In [152]: %timeit broadcasted_indexing(array,idxs)
100 loops, best of 3: 5.01 ms per loop
非常感謝簡化版本。我不完全明白,爲什麼這不僅僅是'array [idxs.T]'。它總是會嘗試匹配多個索引向量,但是當維度的索引是隱式的時候不這樣做。 – Albert
這種事情也經常讓我起牀。理解一維情況要容易得多。 'idxs.T'被解釋爲行索引的2D數組,因此如果'array'是一個'(m,)'1D數組,那麼'array [idxs.T]'將具有形狀'(m,n)'(因爲你從每一行多次採樣)。在你的情況下'array'已經是'(m,n)',所以'array [idxs.T]'的結果是'(m,n,n)',因爲numpy保持'現有'列的尺寸。要摺疊「現有」列維度,您需要爲其指定另一個一維向量。 –