可变宽度大小的Python峰值检测

这是一个峰值检测例程,可以根据需要运行.但是,我想使其更加灵活.

def peak2(x,y,dp,dv):

# Define two arrays: one for the peaks and one
# for the valleys

  peaks=[]
  valleys=[]

# Create two arrays, one for x, and one for y, where each
# element of the new array # consists of three adjacent
# elements of the old array.

  xt=zip(x,x[1:],x[2:])
  yt=zip(y,y[1:],y[2:])

# Walk through these arrays, checking to see if the middle
# value of the three old elements exceeds its neighbors by
# d or more.

  idx=1
  for i,j in zip(xt,yt):
    if(j[1]-j[0]>dp and j[1]-j[2]>dp):
      peaks.append((x[idx],y[idx]))
    elif (j[0]-j[1]>dv and j[2]-j[1]>dv):
      valleys.append((x[idx],y[idx]))
    idx+=1

  return array(peaks),array(valleys)

如您所见,它通过将一个值与其左右邻居进行比较来检测一个峰.并且,如果中心值比其两个紧邻的中心都大某个阈值,则将其视为峰值.寻找山谷的类似逻辑.

我想扩展它,以便将中心值与每一侧的n个邻居进行比较.我将参数传递给函数(称为w),如果w = 3,则执行以下操作:

xt=zip(x,x[1:],x[2:])
yt=zip(y,y[1:],y[2:])

这是当前例程中的内容.但是如果w = 5,那么我想要这个:

xt=zip(x,x[1:],x[2:],x[3:],x[4:])
yt=zip(y,y[1:],y[2:],y[3:],y[4:])

如果w = n,其中n是奇数,那么我想要这个:

xt=zip(x,x[1:],x[2:],...,x[n:])
yt=zip(y,y[1:],y[2:],...,y[n:])

那么,如何在每个元素包含其他数组的n个元素的情况下构建这些数组呢?

解决方法:

您可以使用带有slice的range来构建参数列表,然后使用解包(带有*)将其传递给zip:

xt = zip(*[x[slice(i, None)] for i in xrange(n)]) # use range in Python 3
yt = zip(*[y[slice(i, None)] for i in xrange(n)])

如果您可能有两个以上的维度,则最好一次构建切片列表,然后将其与map和list .__ getitem__一起使用以创建新的列表切片:

slices = [slice(i, None) for i in xrange(n)]
xt = zip(*map(x.__getitem__, slices)
yt = zip(*map(y.__getitem__, slices)
zt = zip(*map(z.__getitem__, slices)

另外请注意,由于列表参数的大小不是恒定的,并且在最短的子列表用尽时(此情况下为最后一个切片),zip会停止,因此您可以考虑使用itertools.izip_longest.

上一篇:检查Java中的字典中是否存在元组键


下一篇:c# List 按类的指定字段排序