在删除容易出错的值时避免使用python循环

时间:2016-06-27 11:39:33

标签: python numpy vectorization

我的时间轴存储在简单的numpy Arrays中,它们很长(> 1000万次)

我必须检测机器停机,它显示在时间向量的跳转中。关机之后,我想删除接下来的10个值(传感器在开机后会暂时给出不良结果)并继续。

我想出了以下代码:

Keep_data=np.empty_like(Timestamp_new,dtype=np.bool)                                
Keep_data[0]=False
Keep_data[1:]=Timestamp_new[1:]>(Timestamp_new[:-1]+min_shutdown_length)

for item in np.nonzero(np.logical_not(Keep_data))[0]:
    Keep_data[item:min(item+10,len(Keep_data)]=False

Timestampnew=Timestampnew[Keep_data]

任何人都可以建议一个更有效的代码,没有纯粹的Python循环吗?

谢谢。

1 个答案:

答案 0 :(得分:2)

基本上,您正在尝试传播/增长或使用dilate False区域的图像处理术语。同样,我们有一个内置的scipy's binary_dilation。现在,您正在尝试使其从输入数组False中的每个此类Keep_data元素开始向更高的索引增长。因此,我们需要使用不同的偏移量(或scipy称之为:origin)而不是默认值0,否则每个元素的两端都会扩展。

因此,总而言之,使用它来实现摆脱代码的循环部分,我们会有这样的实现 -

N = 10   # Interval length
dilated_mask = binary_dilation(~Keep_data, structure=np.ones(N),origin=-int(N/2))
Keep_data[dilated_mask] = False

另一种方法更接近于在问题中作为循环代码发布的方法,但使用NumPy's broadcasting feature进行矢量化,看起来像这样 -

N = 10   # Interval length
idx = np.nonzero(np.logical_not(Keep_data[:-N]))[0]
Keep_datac[(idx + np.arange(N)[:,None]).ravel()] = False
rest = np.nonzero(np.logical_not(Keep_data[-N:]))[0]
if len(rest)>0:
    Keep_datac[-N+rest[0]:] = False