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