根据条件快速舍入数组值

时间:2017-07-14 20:55:42

标签: python performance numpy vectorization

我有一个这样的数组:

a = np.array([
     [0.02, 1.01, 4.01, 3.00, 5.12],
     [2.11, 1.50, 3.98, 0.52, 5.01]])

和"条件"阵列:

c = np.array([0, 1, 4, 5])

如果a[i][j]=c[k],我想围绕c[k] - const < a[i][j] < c[k] + const,否则a[i][j] = 0

例如,如果const = 0.05。结果可能是:

a_result = [[0 1 4 0 0]
            [0 0 4 0 5]]

导航方式是使用3 for循环来检查每个a[i][j]c[k]。但是,当a很大时,它会很慢。我们是否有快速的蟒蛇方式&#34;这样做?

for loop(slow)solution:

a_result = np.full(a.shape, 0)    
const = 0.05     
mh, mw = a.shape
for i in range(mh-1):
   for j in range(mw-1):
      for k in range(1, len(c)):
                if a[i][j] > (c[k] - const) and a[i][j] < (c[k] + const): 
                    a_result[i][j] = c[k] 

1 个答案:

答案 0 :(得分:2)

方法#1

一种矢量化方法是broadcasting -

c[(np.abs(a - c[:,None,None]) < const).argmax(0)]

示例运行 -

In [312]: a
Out[312]: 
array([[ 0.02,  1.01,  4.01,  3.  ,  5.12],
       [ 2.11,  1.5 ,  3.98,  0.52,  5.01]])

In [313]: c
Out[313]: array([0, 1, 4, 5])

In [314]: c[(np.abs(a - c[:,None,None]) < const).argmax(0)]
Out[314]: 
array([[0, 1, 4, 0, 0],
       [0, 0, 4, 0, 5]])

方法#2

另一个更接近我们在问题中的内容,但是矢量化,就像这样 -

mask = ((c[:,None,None] - const)  < a) & (a < (c[:,None,None] + const))
out = c[mask.argmax(0)]

方法#3

根据this post -

,这是考虑到记忆效率的另一个问题
idx = np.searchsorted(c, a, side="left").clip(max=c.size-1)
mask = (idx > 0) &  \
     ( (idx == len(xx)) | (np.fabs(yy - xx[idx-1]) < np.fabs(yy - xx[idx])) )
idx0 = idx-mask
out = xx[idx0]
out[np.abs(c[idx0] - a) >= const] = 0