加速Numpy Masking

时间:2016-10-13 20:32:41

标签: python arrays performance numpy masking

在考虑如何优化时,我仍然是一个不成熟的人。我有这段代码,它接收找到的峰的列表,并找到这些峰的位置,+ / - 某个值,位于多维数组中。然后它将它们的零索引添加+1。代码运行良好,但执行需要很长时间。例如,如果ind具有270个值且refVals具有(3050,3130,80)的形状,则需要接近45分钟才能运行。我知道它有很多数据要流失,但有没有更有效的方法来解决这个问题?

maskData = np.zeros_like(refVals).astype(np.int16)

for peak in ind:
        tmpArr = np.ma.masked_outside(refVals,x[peak]-2,x[peak]+2).astype(np.int16)
        maskData[tmpArr.mask == False  ] += 1
        tmpArr = None

maskData = np.sum(maskData,axis=2)

1 个答案:

答案 0 :(得分:2)

方法#1:内存允许,这是使用broadcasting的矢量化方法 -

# Craate +,-2 limits usind ind
r = x[ind[:,None]] + [-2,2]

# Use limits to get inside matches and sum over the iterative and last dim
mask = (refVals >= r[:,None,None,None,0]) & (refVals <= r[:,None,None,None,1])
out = mask.sum(axis=(0,3))

方法#2:如果内存与前一个内存不足,我们可以使用循环并使用NumPy布尔数组,这可能比屏蔽数组更有效。此外,我们还会执行sum-reduction的另一个级别,以便在跨越迭代时我们可以拖动更少的数据。因此,替代实现看起来像这样 -

out = np.zeros(refVals.shape[:2]).astype(np.int16)
x_ind = x[ind]
for i in x_ind:
    out += ((refVals >= i-2) & (refVals <= i+2)).sum(-1)

方法#3:或者,我们可以在方法#2中用np.isclose替换基于限制的比较。因此,循环内的唯一步骤将变为 -

out += np.isclose(refVals,i,atol=2).sum(-1)