Moj*_*Moj 3 python numpy vectorization
作为我项目的一部分,我需要找到一个向量中是否有4个或更多个连续元素以及它们的索引.目前我使用以下代码:
#sample arrays:
#a1 = np.array([0, 1, 2, 3, 5])
#a2 = np.array([0, 1, 3, 4, 5, 6])
#a3 = np.array([0, 1, 3, 4, 5])
a4 = array([0, 1, 2, 4, 5, 6])
dd = np.diff(a4) #array([1, 1, 2, 1, 1])
c = 0
idx = []
for i in range(len(dd)):
if dd[i]==1 and c<3:
idx.append(i)
c+=1
elif dd[i]!=1 and c>=3:
break
else:
c=0
idx=[]
Run Code Online (Sandbox Code Playgroud)
我有兴趣看看是否有可能避免for循环并只使用numpy函数来完成这项任务.
这将为您提供一个包含所有连续块长度的数组:
np.diff(np.concatenate(([-1],) + np.nonzero(np.diff(a) != 1) + ([len(a)-1],)))
Run Code Online (Sandbox Code Playgroud)
一些测试:
>>> a = [1, 2, 3, 4, 5, 6, 9, 10, 11, 14, 17, 18, 19, 20, 21]
>>> np.diff(np.concatenate(([-1],) + np.nonzero(np.diff(a) != 1) +
([len(a)-1],)))
array([6, 3, 1, 5], dtype=int64)
>>> a = [0, 1, 2, 4, 5, 6]
>>> np.diff(np.concatenate(([-1],) + np.nonzero(np.diff(a) != 1) +
([len(a)-1],)))
array([3, 3], dtype=int64)
Run Code Online (Sandbox Code Playgroud)
要检查是否有至少4项长,请将上面的代码包装成np.any(... >= 4).
要了解其工作原理,我们可以从内到外计算出第一个示例:
>>> a = [1, 2, 3, 4, 5, 6, 9, 10, 11, 14, 17, 18, 19, 20, 21]
Run Code Online (Sandbox Code Playgroud)
首先,我们计算出连续项之间的增量:
>>> np.diff(a)
array([1, 1, 1, 1, 1, 3, 1, 1, 3, 3, 1, 1, 1, 1])
Run Code Online (Sandbox Code Playgroud)
然后,我们确定delta不是的1位置,即一大块连续项开始或结束的位置:
>>> np.diff(a) != 1
array([False, False, False, False, False, True, False, False, True,
True, False, False, False, False], dtype=bool)
Run Code Online (Sandbox Code Playgroud)
我们提取Trues 的位置:
>>> np.nonzero(np.diff(a) != 1)
(array([5, 8, 9], dtype=int64),)
Run Code Online (Sandbox Code Playgroud)
上述指数标志着连续连胜的最后一项.蟒切片被定义为start至last+1,因此我们可以由一个递增该阵列中,添加在开始零和所述阵列的端部的长度,并已所有的起始和结束的连续序列,即指数:
>>> np.concatenate(([0], np.nonzero(np.diff(a) != 1)[0] + 1, [len(a)]))
array([ 0, 6, 9, 10, 15], dtype=int64)
Run Code Online (Sandbox Code Playgroud)
从连续索引中获取差异将给出每个连续块的期望长度.因为我们所关心的只是差异,而不是在索引中添加一个,在我的原始答案中,我选择了前置-1和追加len(a)-1:
>>> np.concatenate(([-1],) + np.nonzero(np.diff(a) != 1) + ([len(a)-1],))
array([-1, 5, 8, 9, 14], dtype=int64)
>>> np.diff(np.concatenate(([-1],) + np.nonzero(np.diff(a) != 1) +
([len(a)-1],)))
array([6, 3, 1, 5], dtype=int64)
Run Code Online (Sandbox Code Playgroud)
假设您在此数组中标识出您想要5项目块的索引,即3该数组的位置.要恢复该块的开始和停止索引,您可以简单地执行:
>>> np.concatenate(([0], np.nonzero(np.diff(a) != 1)[0] + 1, [len(a)]))[3:3+2]
array([10, 15], dtype=int64)
>>> a[10:15]
[17, 18, 19, 20, 21]
Run Code Online (Sandbox Code Playgroud)