使用scipy.signal.argrelextrema同时查找本地最小值和最大值

时间:2017-11-12 18:03:03

标签: python numpy scipy

我想在数组中同时找到局部最小值和最大值。我试图使用Scipy的argrelextrema,但是我找不到任何关于所需比较器功能的文档。我试图写自己没有成功。我怎么能这样做?

我想这样做,但只调用argrelextrema一次,而不是使用argrelminargrelmax两次迭代数据,因为我的数据很长,而且我有用它多次这样做:

   import numpy as np
   import scipy.signal as sg

   data = [[xes], [ys]]   #a long 2d array
   max_places = np.array(sg.argrelmax(data[1]))[0] 
   min_places = np.array(sg.argrelmin(data[1]))[0]
   extrema_places = np.contantenate((max_places, min_places))

1 个答案:

答案 0 :(得分:1)

你的目标没有意义。

使用文档中的示例:

In [199]: from scipy.signal import argrelextrema
In [200]:  x = np.array([2, 1, 2, 3, 2, 0, 1, 0])
In [201]: argrelextrema(x, np.greater)
Out[201]: (array([3, 6], dtype=int32),)

这会得到局部最大值。更改为less以获取当地最低标准。

In [202]: argrelextrema(x, np.less)
Out[202]: (array([1, 5], dtype=int32),)

lambda功能可以代替np.greater

In [204]: argrelextrema(x, lambda a,b: a>b)
Out[204]: (array([3, 6], dtype=int32),)

我们可以组合>和<使用或,但只是获取所有点(除了结尾)。

In [205]: argrelextrema(x, lambda a,b: (a>b) | (a<b))
Out[205]: (array([1, 2, 3, 4, 5, 6], dtype=int32),)

更改x的值,使两个相邻的值相同(因此lambda测试为false)

In [211]: x
Out[211]: array([2, 1, 2, 3, 2, 2, 1, 0])
In [212]: argrelextrema(x, lambda a,b: (a>b) | (a<b))
Out[212]: (array([1, 2, 3, 6], dtype=int32),)

但是我们可以说你可以给它想要的功能,你想要什么样的结果?最大值和最小值串联为一个数组,或两个数组,还是二维数组?

np.array([1,3,5,6])
(np.array([3,6]), np.array([1,5]))

刚刚意识到结果已经是一个元组,比如where,每个维度一个数组。事实上,这就是它的回报:

results = _boolrelextrema(data, comparator,
                          axis, order, mode)
return np.where(results)

任务的核心在于_boolrelextrama功能;可能会返回类似data的数组,但基于comparator返回True / False。

你是否正朝着两个方向寻找转折点?您可能想要使用order

In [217]: argrelextrema(x, lambda a,b: (a>b) | (a<b), order=2)
Out[217]: (array([1, 3, 6], dtype=int32),)

使用修改后的x,此订单2版本确实返回两​​个极值。但我怀疑如果转弯之间的运行时间更长,它是否有效。

请参阅sg._peak_finding.py中的完整代码(另请参阅文档中的[source]链接)。 _boolrelextrema使用comparator针对data的多个移位版本测试datamode使用了np.take

详细说明

argrelmax正在做:

In [262]: x = np.array([2, 1, 2, 3, 2, 0, 1, 0])   # data
In [263]: locs = np.arange(0,len(x))          # all indices
In [264]: plus=np.take(x,locs+1,mode='clip')   # shift up, with 'clip'
In [265]: minus=np.take(x,locs-1,mode='clip')  # shift down
In [266]: plus
Out[266]: array([1, 2, 3, 2, 0, 1, 0, 0])
In [267]: minus
Out[267]: array([2, 2, 1, 2, 3, 2, 0, 1])
In [268]: (x>plus) & (x>minus)             # compare x with shifted arrays
Out[268]: array([False, False, False,  True, False, False,  True, False], dtype=bool)
In [269]: np.where(_)
Out[269]: (array([3, 6], dtype=int32),)

argrelmin生成相同的plusminus,但接着会这样做:

In [270]: np.where((x<plus) & (x<minus))
Out[270]: (array([1, 5], dtype=int32),)

where交织索引之前执行'或'步骤:

In [271]: np.where(((x<plus) & (x<minus)) | (x>plus) & (x>minus))
Out[271]: (array([1, 3, 5, 6], dtype=int32),)

合并min_max可以节省2 take次操作,但除此之外它还执行相同的2个比较步骤。

请注意,所有这些操作都在编译代码中;数据阵列上没有Python级迭代。