2015-04-02 65 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.])