Python:将点分配到垃圾箱的更快或更无循环的方法?

Sib*_*ing 5 python performance numpy vectorization

我有一个N×2的N 2D点数组,我想将其分配给M×K的箱格。

例如,点[m + 0.1, k][m + 0.1, k + 0.9]应该落入bin [m, k],其中mk均为整数。一点可能没有落入任何垃圾箱中。

在实现方面,我希望将结果存储在逻辑上,如果点落入bin的MbyKbyN 数组in_bin中。in_bin[m, k, n]Truen[m, k]

这就是我天真的使用双循环的方式。

M = 10
K = 11
N = 100
pts = 20 * np.random.rand(N, 2)
in_bin = np.zeros((M, K, N), dtype=bool)
for m in range(M):
    for k in range(K):
        inbin_h = (pts[:, 0] >= m) & (pts[:, 0] < (m + 1))
        inbin_w = (pts[:, 1] >= k) & (pts[:, 1] < (k + 1))
        in_bin[m, k, np.where(inbin_h & inbin_w)[0]] = True
Run Code Online (Sandbox Code Playgroud)

hpa*_*ulj 3

where实际上并不需要(这不会改变速度太多):

In [120]: in_bin1 = np.zeros((M, K, N), dtype=bool) 
     ...: for m in range(M): 
     ...:     for k in range(K): 
     ...:         inbin_h = (pts[:, 0] >= m) & (pts[:, 0] < (m + 1)) 
     ...:         inbin_w = (pts[:, 1] >= k) & (pts[:, 1] < (k + 1)) 
     ...:         in_bin1[m, k, inbin_h & inbin_w] = True 
Run Code Online (Sandbox Code Playgroud)

但我们可以一次性为m所有人进行分配:k

In [125]: x0=(pts[:,0]>=np.arange(M)[:,None]) & (pts[:,0]<np.arange(1,M+1)[:,None]);                                                            
In [126]: x1=(pts[:,1]>=np.arange(K)[:,None]) & (pts[:,1]<np.arange(1,K+1)[:,None]);  
In [127]: x0.shape                                                           
Out[127]: (10, 100)
In [128]: x1.shape                                                           
Out[128]: (11, 100)
Run Code Online (Sandbox Code Playgroud)

将这些与广播结合起来:

In [129]: xx = x0[:,None,:] & x1[None,:,:]                                   
In [130]: xx.shape                                                           
Out[130]: (10, 11, 100)
In [131]: np.allclose(in_bin1, xx)    # and check                                        
Out[131]: True
Run Code Online (Sandbox Code Playgroud)