Python numpy如何在1darray上找到邻域中的局部最小值

Python numpy如何在1darray上找到邻域中的局部最小值,python,numpy,scipy,Python,Numpy,Scipy,我有一份分类样本的清单。它们是按采样时间排序的,每一个采样都是在前一个采样后一秒钟进行的。 我想在指定大小的邻域中找到最小值 例如,假设邻域大小为2,且样本大小如下: samples = [ 5, 12.3, 12.3, 7, 2, 6, 9, 10, 5, 9, 17, 2 ] 我希望得到以下输出:[5,2,5,2] 在numpy/scipy实现这一目标的最佳方式是什么 编辑:解释了最小值背后的原因: 5-旁边的2号窗口为[12.3 12.3]。5号更小 2-左边[12.3,7]右边[6.9

我有一份分类样本的清单。它们是按采样时间排序的,每一个采样都是在前一个采样后一秒钟进行的。 我想在指定大小的邻域中找到最小值

例如,假设邻域大小为2,且样本大小如下:

samples = [ 5, 12.3, 12.3, 7, 2, 6, 9, 10, 5, 9, 17, 2 ]
我希望得到以下输出:[5,2,5,2] 在numpy/scipy实现这一目标的最佳方式是什么

编辑:解释了最小值背后的原因:

  • 5-旁边的2号窗口为[12.3 12.3]。5号更小
  • 2-左边[12.3,7]右边[6.9]。2是最小值
  • 5-向左[9 10]向右[9 17]。5是最小值
  • 请注意,9不是最小值,它的左右两侧有一个2窗口,其值较小(2)


    正如Divakar在评论中指出的,这就是滑动窗口产生的结果。如果要删除重复项,可以单独执行

    这将查看每个窗口,找到最小值,如果窗口的最小值不等于最近添加的值,则将其添加到列表中

    samples = [5, 12.3, 12.3, 7, 2, 6, 9, 10, 5, 9, 17, 2]
    neighborhood = 2
    
    minima = []
    for i in xrange(len(samples)):
      window = samples[max(0, i - neighborhood):i + neighborhood + 1]
      windowMin = min(window)
      if minima == [] or windowMin != minima[-1]:
        minima.append(windowMin)
    
    这将提供您描述的输出:

    print minima
    > [5, 2, 5, 2]
    
    然而,@imaluengo的答案更好,因为如果两个连续的最小值在原始列表中有不同的索引,那么它将包括这两个连续的最小值

    使用scipy的:

    这表明位置4和8(
    2
    5
    )的数字是2号街区中最小的数字。由于
    argrelextrema
    仅支持
    clip
    wrap
    边界条件,因此未检测到边界处的数字(
    5
    2
    )。至于你的问题,我想你也对它们感兴趣。要检测它们,很容易首先添加反射边界条件:

    >>> new_data = np.pad(data, radius, mode='reflect')
    >>> new_data
    array([ 12.3,  12.3,   5. ,  12.3,  12.3,   7. ,   2. ,   6. ,   9. ,
            10. ,   5. ,   9. ,  17. ,   2. ,  17. ,   9. ])
    
    利用具有相应边界条件的数据,我们现在可以应用previus极值检测器:

    >>> arg_minimas = argrelextrema(new_data, np.less, order=radius)[0] - radius
    >>> arg_minimas
    array([ 0,  4,  8, 11])
    
    它返回局部极值(本例中为最小值,因为
    np.less
    )出现在
    半径=2的滑动窗口中的位置

    注意
    -radius
    ,在使用
    reflect
    将数组包装为带有
    np.pad
    的边界条件后,修复
    +radius
    索引

    编辑:如果您是在值中而不是在位置中安装的,则它是直接的:

    >>>  data[arg_minimas]
    array([ 5.,  2.,  5.,  2.])
    

    看起来,基本上你是在滑动窗口中找到局部极小值,但是滑动窗口的滑动方式是,前一个窗口的结束作为新窗口的开始。对于这样一个特定的问题,本解决方案中建议的是使用-

    样本运行

    运行#1:原始输入数据

    In [105]: S     # Input array
    Out[105]: 
    array([  5. ,  12.3,  12.3,   7. ,   2. ,   6. ,   9. ,  10. ,   5. ,
             9. ,  17. ,   2. ])
    
    In [106]: N   # Window radius
    Out[106]: 2
    
    In [107]: out  # Output array
    Out[107]: array([ 5.,  2.,  5.,  2.])
    
    运行#2:修改输入数据,窗口半径=2

    In [101]: S     # Input array
    Out[101]: 
    array([  5. ,  12.3,  12.3,   7. ,   2. ,   6. ,   9. ,  10. ,   5. ,
             9. ,  17. ,   2. ,   0. ,  -3. ,   7. ,  99. ,   1. ,   0. ,
            -4. ,  -2. ])
    
    In [102]: N   # Window radius
    Out[102]: 2
    
    In [103]: out  # Output array
    Out[103]: array([ 5.,  2.,  5., -3., -4., -4.])
    
    运行#3:修改输入数据,窗口半径=3

    In [97]: S    # Input array
    Out[97]: 
    array([  5. ,  12.3,  12.3,   7. ,   2. ,   6. ,   9. ,  10. ,   5. ,
             9. ,  17. ,   2. ,   0. ,  -3. ,   7. ,  99. ,   1. ,   0. ,
            -4. ,  -2. ])
    
    In [98]: N   # Window radius
    Out[98]: 3
    
    In [99]: out  # Output array
    Out[99]: array([ 5.,  2., -3., -4.])
    

    这是你要找的滑动窗口中的最小值吗?如果是,4个元素的输出数组大小如何?你能解释一下你是如何得到预期的输出的吗?对于samples=[5,4,3,2,1]的输出应该是什么,对于samples=[5,5,5,5,5,5,5,5]的输出应该是什么?我认为这不管用,试试
    samples=[5,4,3,2,1]
    它会回答
    [3,2,1]
    但很明显,3不是本地最低要求。@StefanPochmann我的解释是这是期望的行为,尽管我可能误解了询问者的意图。3不是局部最小值,但它是在迭代中测试的指定大小附近的最小值。是的,我同意,它不清楚。标题和正文似乎要求不同的东西。你的解释可能是对的。
    In [105]: S     # Input array
    Out[105]: 
    array([  5. ,  12.3,  12.3,   7. ,   2. ,   6. ,   9. ,  10. ,   5. ,
             9. ,  17. ,   2. ])
    
    In [106]: N   # Window radius
    Out[106]: 2
    
    In [107]: out  # Output array
    Out[107]: array([ 5.,  2.,  5.,  2.])
    
    In [101]: S     # Input array
    Out[101]: 
    array([  5. ,  12.3,  12.3,   7. ,   2. ,   6. ,   9. ,  10. ,   5. ,
             9. ,  17. ,   2. ,   0. ,  -3. ,   7. ,  99. ,   1. ,   0. ,
            -4. ,  -2. ])
    
    In [102]: N   # Window radius
    Out[102]: 2
    
    In [103]: out  # Output array
    Out[103]: array([ 5.,  2.,  5., -3., -4., -4.])
    
    In [97]: S    # Input array
    Out[97]: 
    array([  5. ,  12.3,  12.3,   7. ,   2. ,   6. ,   9. ,  10. ,   5. ,
             9. ,  17. ,   2. ,   0. ,  -3. ,   7. ,  99. ,   1. ,   0. ,
            -4. ,  -2. ])
    
    In [98]: N   # Window radius
    Out[98]: 3
    
    In [99]: out  # Output array
    Out[99]: array([ 5.,  2., -3., -4.])