【问题标题】:find_peaks does not identify a peak at the start of the arrayfind_peaks 未识别数组开头的峰值
【发布时间】:2020-05-22 13:24:30
【问题描述】:

我正在尝试找到一种矢量化方法来查找数组中的第一个位置,其中值没有高于 n 个先前数字的最大值。我想过使用 scipy.signal 的 find_peaks 方法来查找局部最大值。我认为如果您将距离定义为假设 10 n 是 10,那么它确实可以做到这一点。但不幸的是,距离的条件必须在两个方向上都满足 - 先前和即将到来的数字。有没有其他方法或方法可以找到这样的东西?

示例:

arr1 = np.array([1.        , 0.73381293, 0.75649351, 0.77693474, 0.77884614,
       0.81055903, 0.81402439, 0.78798586, 0.78839588, 0.82967961,
       0.8448    , 0.83276451, 0.82539684, 0.81762916, 0.82722515,
       0.82101804, 0.82871127, 0.82825041, 0.82086957, 0.8347826 ,
       0.82666665, 0.82352942, 0.81270903, 0.81191224, 0.83180428,
       0.84975767, 0.84044236, 0.85057473, 0.8394649 , 0.80000001,
       0.83870965, 0.83962262, 0.85039371, 0.83359748, 0.84019768,
       0.83281732, 0.83660132])

from scipy.signal import find_peaks
peaks, _ = find_peaks(arr1, distance=10)

在这种情况下,它会找到位置 10 和 27。但位置 0 也有 10 个不更高的后续元素。我怎样才能找到这些?

【问题讨论】:

  • 发布的任何一个最终都为您工作了吗?

标签: python numpy scipy vectorization


【解决方案1】:

不幸的是,find_peaks() 通过比较相邻值来工作 - 因此无法识别出现在数组开头或结尾的峰值。一种解决方法是使用np.concatenate()在开头和结尾插入数组的最小值,然后从peaks变量中减去1:

>>> import numpy as np
>>> peaks, _ = find_peaks(np.concatenate(([min(arr1)],arr1,[min(arr1)])), distance=10)
>>> peaks-1
array([ 0, 10, 27], dtype=int64)

【讨论】:

    【解决方案2】:
    def rolling_window(a, window):
        shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
        strides = a.strides + (a.strides[-1],)
        return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)
    
    def get_peaks(arr, window):
        maxss = np.argmax(rolling_window(arr1, window), axis=1)
        return np.where(maxss == 0)[0]
    
    >>> arr1 = np.array([1.        , 0.73381293, 0.75649351, 0.77693474, 0.77884614,
           0.81055903, 0.81402439, 0.78798586, 0.78839588, 0.82967961,
           0.8448    , 0.83276451, 0.82539684, 0.81762916, 0.82722515,
           0.82101804, 0.82871127, 0.82825041, 0.82086957, 0.8347826 ,
           0.82666665, 0.82352942, 0.81270903, 0.81191224, 0.83180428,
           0.84975767, 0.84044236, 0.85057473, 0.8394649 , 0.80000001,
           0.83870965, 0.83962262, 0.85039371, 0.83359748, 0.84019768,
           0.83281732, 0.83660132])
    >>> get_peaks(arr1, 10)
    array([ 0, 10, 27])
    
    

    滚动窗口功能的功劳:Rolling window for 1D arrays in Numpy?

    【讨论】:

      【解决方案3】:

      我们可以使用1D sliding-windowed max filter from SciPy。此外,您似乎正在与 n 以前的元素进行比较。因为,第一个元素不会有任何先前的元素,我们需要让它忽略。

      因此,我们会有这样的实现 -

      from scipy.ndimage.filters import maximum_filter1d
      
      def peaks_previousN(a, n):
          W = (n-1)//2
          return np.flatnonzero(a[1:]>=maximum_filter1d(a, n, origin=W)[:-1])+1
      

      使用给定的样本数组运行样本 -

      In [107]: peaks_previousN(arr1, n=10)
      Out[107]: array([25, 27])
      

      【讨论】:

      • 你是对的。也许我在寻找正确的方法时感到困惑。我正在寻找最大值没有改变 10 个元素长度的第一个位置。所以它将是索引 10。因为 10 元素的最大值没有改变。所以我认为找到 scipy 信号的峰值正是我正在寻找的。​​span>
      • @Varlor 那么,您是说将当前元素与包括或不包括当前元素的最后 10 个元素进行比较?
      • 当前对最后 10 个,不包括当前元素。我只需要第一次出现
      • @Varlor 然后,我认为n = 10 的最终预期输出将是[25,27]10 不会出现,因为 arr1[0:10].max()1.0a[10]0.8448。同样,0 不会出现,因为它没有先前的元素。我说的对吗?
      • 0 不会完全存在,因为我们正在寻找总体最大值没有改变 n 个元素的索引。但它会是 10,因为 a[10] 是 0.8448 并且不高于 1。所以最大值仍然是 1.0 并且满足条件。抱歉,如果我之前不够清楚
      猜你喜欢
      • 1970-01-01
      • 2021-03-26
      • 1970-01-01
      • 2012-09-06
      • 2019-03-14
      • 2019-08-10
      • 1970-01-01
      • 2013-02-11
      • 1970-01-01
      相关资源
      最近更新 更多