2016-12-26 49 views
9

我有兩個三維陣列a和b,並且希望找到b的2D子陣列,其中a沿着第三個軸線具有最小值,即在另一個陣列中查找對應於最小值的陣列

a=n.random.rand(20).reshape((5,2,2)) 
b=n.arange(20).reshape((5,2,2)) 
c=n.argmin(a,2) #indices with minimal value of a 
d=n.zeros_like(c) #the array I want 
for i in range(5): 
    for j in range(2): 
    d[i,j] = b[i,j,c[i,j]] 

有沒有一種方法,我可以得到這些值沒有雙循環?

我知道這個答案: replace min value to another in numpy array 但是如果我想這對我的3D陣列的工作,我不得不做大量的重塑操作的 - 我不知道是否有更簡單的東西。

回答

1

下面是一個使用fancy-indexing的方法 -

m,n,r = b.shape 
d_out = b[np.arange(m)[:,None],np.arange(n),c] 
1

這裏是一個Numpythonic方式:

In [83]: x, y, z = a.shape 
In [84]: b[np.repeat(np.arange(x), y), np.tile(np.arange(y), x), c.ravel()].reshape(x, y) 

這裏np.repeat(np.arange(x), y)會給你第一軸的相應指標。

In [86]: np.repeat(np.arange(x), y) 
Out[86]: array([0, 0, 1, 1, 2, 2, 3, 3, 4, 4]) 

np.tile(np.arange(y), x)會給你第二軸的相應指標。

In [87]: np.tile(np.arange(y), x) 
Out[87]: array([0, 1, 0, 1, 0, 1, 0, 1, 0, 1]) 

而對於第三個,你可以使用扁平形狀c

In [88]: c.ravel() 
Out[88]: array([1, 0, 1, 1, 1, 0, 1, 1, 0, 0]) 
+0

重塑這些到(5,2),結果應該看起來像'mgrid'版'ogrid'建議的另一個答案。 – hpaulj

+0

@hpaulj是的,不幸的是我不熟悉那個功能。 – Kasramvd

3

您可以使用np.ogrid創建網格爲其他尺寸:

x, y, z = arr.shape # assuming your array is named "arr" 
xyz = np.ogrid[0:x, 0:y] + [c] # c is your second axis index (the argmin) 
arr[xyz] 

如果不是最後一個軸,那麼你可以簡單地使用insert因爲ogrid返回一個包含指數正常的Python列表。

+0

只需檢查: n.ogrid [0:x,0:y] + [c] 向ogrid-array添加第三維,c的元素正確嗎?所以這看起來與花哨索引的答案非常相似(我已經接受,因爲它更短,但這很有趣 - 謝謝!)。 – mzzx

+0

@ mzzx基本上類似的答案,因爲兩者都創建廣播範圍數組以索引數據數組。區別就在於這些範圍數組的創建方式。我的文章明確地進行了廣播,而這篇文章是通過函數的幫助完成的。 – Divakar

+0

@mzzx是的,它們是相同的!如果你喜歡它,你也可以寫在一行:arr [np.ogrid [0:arr.shape [0],0:arr.shape [1]] + [c]] :-) – MSeifert