【问题标题】:Find local minima and maxima simultanously with scipy.signal.argrelextrema使用 scipy.signal.argrelextrema 同时查找局部最小值和最大值
【发布时间】:2018-04-25 09:56:50
【问题描述】:

我想在一个数组中同时找到局部最小值和最大值。我尝试使用 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))

【问题讨论】:

    标签: python numpy scipy


    【解决方案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 测试为假)

    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 的真/假。

    您是否正在寻找一个转折点,无论是哪个方向?你可能想玩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 来测试 datadata 的几个转换版本。 modenp.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 级迭代。

    【讨论】:

    • 我认为你误解了我的目标。它不是找到不等于任何相邻点的所有点,而是在单个数组中获取最小值和最大值的索引,而不需要对数据进行两次迭代。我添加了一个更好的示例,原来的示例可能具有误导性。
    • argrelmax 只是argrelextrema(data, np.greater, axis, order, mode)。我证明了这一点,但没有 concatenate 将 2 个数组合并为一个。
    • CONFUSION ...请写清楚..你想解释什么???
    • @shantanupathak,如果您在特定问题上需要帮助,请提出您自己的问题。不要尝试添加旧答案(其他人认为足够)。有新的问题涉及argrelextrema
    猜你喜欢
    • 2021-09-12
    • 2023-01-05
    • 2018-06-09
    相关资源
    最近更新 更多