2015-04-02 95 views
-1

我使用numpy做一些計算。在下面的代碼中:numpy array slicing避免for循環

assert(len(A.shape) == 2) # A is a 2D nparray 
    d1, d2 = A.shape 
    # want to initial G,which has the same dimension as A. And assign the last column of A to the last column of G 
    # initial with value 0 
    G = zero_likes(A) 
    # assign the last column to that of G 
    G[:, d2-1] = A[:, d2-1] 

    # the columns[0,dw-1] of G is the average of columns [0, dw-1] of A, based on the condition of B 
    for iW in range(d2-1): 
     n = 0 
     sum = 0.0 
     for i in range(d1): 
      if B[i, 0] != iW and B[i, 1] == 0: 
       sum += A[i, iW] 
       n += 1 
     for i in range(d1): 
      if B[i, 0] != iW and B[i, 1] == 0: 
       G[i, iW] = sum/(1.0 * n) 
    return G 

是否有更簡單的方法使用「切片」或「布爾數組」?

謝謝!如果您想G具有相同的維數爲A,然後更改的G適當元素

+4

這將節省一些時間,以饗讀者,如果你情境你的代碼,說的是它的目的。另外/另外,你可以評論你的代碼。 – Antonio 2015-04-02 14:51:38

+0

數組「A」是三維的嗎?否則'G = A [:,d2-1]'和'G [i,iw] = ...'沒有意義。但是,如果這是真的,'sum'也是一個一維數組,這是沒有意義的。請首先修正你顯示的代碼中的錯誤...你的意思是'G = A [:,:d2-1]'? – plonser 2015-04-02 15:21:19

+1

給我們一個工作樣本! – hpaulj 2015-04-02 16:04:26

回答

0

,下面的代碼應該工作:

# create G as a copy of A, otherwise you might change A by changing G 
G = A.copy() 

# getting the mask for all columns except the last one 
m = (B[:,0][:,None] != np.arange(d2-1)[None,:]) & (B[:,1]==0)[:,None] 

# getting a matrix with those elements of A which fulfills the conditions 
C = np.where(m,A[:,:d2-1],0).astype(np.float) 

# get the 'modified' average you use 
avg = np.sum(C,axis=0)/np.sum(m.astype(np.int),axis=0) 

# change the appropriate elements in all the columns except the last one 
G[:,:-1] = np.where(m,avg,A[:,:d2-1]) 

擺弄了半天,發現錯誤後...我結束了這個代碼。我檢查對幾種隨機矩陣AB

A = numpy.random.randint(100,size=(5,10)) 
B = np.column_stack(([4,2,1,3,4],np.zeros(5))) 

,到目前爲止,您的具體選擇和我的結果是一致的。

+0

avg = np.sum(C,axis = 0)/ np .sum(m.astype(np.int),axis = 0),軸應該是1,它將總和整行而不是列。這樣,G [:,: - 1] = np.where(m,avg,A [:,:d2-1])應該如何表示? – stevenhz 2015-04-03 12:40:22

+0

@stevenhz:我的代碼正在做你的代碼正在做的事情,包括假設'G'的起點是什麼。你的代碼沿'axis = 0'而不是'axis = 1'取平均值。糾正你的代碼,並帶上一個簡單的'A'和'B'以及所需的結果'G'。然後,只有這樣,我纔會嘗試再次尋找解決方案。 – plonser 2015-04-03 14:23:09

+0

是的,你是對的。我在這裏錯了。非常感謝,迄今爲止。 – stevenhz 2015-04-04 08:30:20

0

這裏是一個開始,重點對第1內部循環:

In [35]: A=np.arange(12).reshape(3,4) 

In [36]: B=np.array([[0,0],[1,0],[2,0]]) 

In [37]: sum=0 

In [38]: for i in range(3): 
    if B[i,0]!=iW and B[i,1]==0: 
     sum += A[i,iW] 
     print(i,A[i,iW]) 
    ....:   
1 4 
2 8 

In [39]: A[(B[:,0]!=iW)&(B[:,1]==0),iW].sum() 
Out[39]: 12 

我必須提供我自己的樣本數據來進行測試。

第二個循環的條件相同(B[:,0]!=iW)&(B[:,1]==0),應該以相同的方式工作。

正如其中一條評論所言,G的尺寸看起來很有趣。爲了使我的示例能夠正常工作,我們創建一個零數組。它看起來像您要指派給的G選擇的元素,的Asum/n

In [52]: G=np.zeros_like(A) 
In [53]: G[I,iW]=A[I,iW].mean() 

一個子集假設n的均值,求和每個iW術語的數目而變化,則可能難以以壓縮外循環進入矢量化步驟。如果n是相同的,則可以取出與條件匹配的子集A,例如A1,取一個軸上的平均值,將值分配給G。在總數中有不同數量的術語,你仍然需要循環。

它只是發生在我身上,蒙面陣列可能工作。掩蓋不符合條件的條款A,然後採取意思。

In [91]: I=(B[:,[0]]!=np.arange(4))&(B[:,[1]]==0) 

In [92]: I 
Out[92]: 
array([[False, True, True, True], 
     [ True, False, True, True], 
     [ True, True, False, True]], dtype=bool) 

In [93]: A1=np.ma.masked_array(A, ~I) 

In [94]: A1 
Out[94]: 
masked_array(data = 
[[-- 1 2 3] 
[4 -- 6 7] 
[8 9 -- 11]], 
      mask = 
[[ True False False False] 
[False True False False] 
[False False True False]], 
     fill_value = 999999) 

In [95]: A1.mean(0) 
Out[95]: 
masked_array(data = [6.0 5.0 4.0 7.0], 
      mask = [False False False False], 
     fill_value = 1e+20) 

或用plonser'swhere

In [111]: np.where(I,A,0).sum(0)/I.sum(0) 
Out[111]: array([ 6., 5., 4., 7.])