2012-11-27 50 views
3

我有一個numpy的零數組。爲了具體,假設它的2x3x4:在numpy數組中分配值

x = np.zeros((2,3,4)) 

和假設我有隨機整數的2×3陣列從0到3(x的第三維的索引)。

>>> y = sp.stats.distributions.randint.rvs(0, 4, size=(2,3)) 
>>> y 
[[2 1 0] 
[3 2 0]] 

如何有效地執行以下任務(編輯:一些不適合循環使用,適用於X與任意數量的尺寸,並在每個維度任意數量的元素)?

>>> x[0,0,y[0,0]]=1 
>>> x[0,1,y[0,1]]=1 
>>> x[0,2,y[0,2]]=1 
>>> x[1,0,y[1,0]]=1 
>>> x[1,1,y[1,1]]=1 
>>> x[1,2,y[1,2]]=1 
>>> x 
array([[[ 0., 0., 1., 0.], 
     [ 0., 1., 0., 0.], 
     [ 1., 0., 0., 0.]], 

     [[ 0., 0., 0., 1.], 
     [ 0., 0., 1., 0.], 
     [ 1., 0., 0., 0.]]]) 

謝謝, 詹姆斯

回答

1

替換兩個for循環和他們的負擔。在那一刻,我只能想到「簡單」的版本,其中涉及沿前兩個維度壓扁。此代碼應工作:

shape_last = x.shape[-1] 
x.reshape((-1, shape_last))[np.arange(y.size), y.flatten()] = 1 

這個收益率(與我的隨機生成y):

array([[[ 0., 0., 0., 1.], 
     [ 0., 0., 1., 0.], 
     [ 0., 1., 0., 0.]], 

     [[ 0., 1., 0., 0.], 
     [ 0., 0., 0., 1.], 
     [ 0., 1., 0., 0.]]]) 

的關鍵是,如果你使用多個numpy的陣列(advanced indexing)做索引,numpy的將使用索引對索引到數組中。

當然,確保xy兩者都被C-訂單或F-順序 - 否則,以reshapeflatten的通話可能給不同的訂單。

+0

這肯定比我使用的for循環更快,它看起來可以很好地縮放每個維度的維數和元素數量。謝謝。 – user1857751

0
x = np.zeros((2,3,4)) 
y=np.array([[2, 1, 0],[3, 2, 0]]) # or y=sp.stats... 
for i in range(2): 
    for j in range(3): 
     x[i,j,y[i,j]]=1 

會產生期望的結果,IIRC。如果陣列的尺寸不會改變,考慮

for j in range(3): 
    x[0,j,y[0,j]] = x[1,j,y[1,j]] = 1 
+1

感謝您的答覆,但問題是,我需要爲大型陣列有效地做到這一點。換句話說,我想避免循環。 – user1857751

+0

我需要能夠處理x的任何尺寸的代碼,即任何數量的尺寸或每個尺寸中的任意數量的元素。 – user1857751

+0

我對numpy不是很熟悉,所以我不知道它是否具有相關的內建函數來完成這項工作。當然有[相關例程](http://docs.scipy.org/doc/numpy/reference/routines.sort.html)argwhere,非零,在哪裏,並提取,可以做相反的,例如可以找到的位置數組中的非零元素 –

1

使用numpy.meshgrid()創建索引數組,您可以使用這些索引索引到原始數組和第三維值的數組中。

import numpy as np 
import scipy as sp 
import scipy.stats.distributions 

a = np.zeros((2,3,4)) 
z = sp.stats.distributions.randint.rvs(0, 4, size=(2,3)) 

xx, yy = np.meshgrid(np.arange(2), np.arange(3)) 
a[ xx, yy, z[xx, yy] ] = 1 
print a 

爲了清楚起見,我已經將數組從x更名爲a,並將索引數組從y更名爲z。

編輯: 4D例如:

a = np.zeros((2,3,4,5)) 
z = sp.stats.distributions.randint.rvs(0, 4, size=(2,3)) 
w = sp.stats.distributions.randint.rvs(0, 5, size=(2,3)) 

xx, yy = np.meshgrid(np.arange(2), np.arange(3)) 
a[ xx, yy, z[xx, yy], w[xx, yy] ] = 1 
+0

感謝您的回覆。你知道如何將它推廣到任何數量的維度嗎? – user1857751

+0

@ user1857751:是的,當然,它以一種直接的方式進行概括。meshgrid在所有維度中創建索引向量,您可以*不*想查找,然後使用這些向量索引原始數組和您想要查找的索引。 –