在Numpy中从一个一维numpy数组中找到超过某一阈值的最大值

4
我的目标是识别出在以下日期时间格式中,存在高于某个阈值的本地极大值。我知道有其他相关的响应处理使用numpy和scipy技术来查找局部最大值和最小值,但据我所知,没有一个响应涉及到一个阈值级别。
我有一个pandas.Series,表示为df_1,它存储了给定时间的整数值:
t_min
2015-12-26 14:45:00      46
2015-12-26 14:46:00      25
2015-12-26 14:47:00      39
2015-12-26 14:48:00      58
2015-12-26 14:49:00      89
2015-12-26 14:50:00      60
2015-12-26 14:51:00      57
2015-12-26 14:52:00      60
2015-12-26 14:53:00      46
2015-12-26 14:54:00      31
2015-12-26 14:55:00      66
2015-12-26 14:56:00      78
2015-12-26 14:57:00      49
2015-12-26 14:58:00      47
2015-12-26 14:59:00      31
2015-12-26 15:00:00      55
2015-12-26 15:01:00      19
2015-12-26 15:02:00      10
2015-12-26 15:03:00      31
2015-12-26 15:04:00      36
2015-12-26 15:05:00      61
2015-12-26 15:06:00      29
2015-12-26 15:07:00      32
2015-12-26 15:08:00      49
2015-12-26 15:09:00      35
2015-12-26 15:10:00      17
2015-12-26 15:11:00      22

我使用以下方法来推断数组索引,在另一个回答找到本地极大值:

x = np.array(df_1, dtype=np.float)

# for local maxima
print argrelextrema(x, np.greater)

然而,我想要生成这些最大值发生的时间数组,而不是使用x[argrelextrema(x, np.greater)[0]]得到的整数(现在转换为浮点数)索引值。 有什么办法可以获得所需时间的数组吗?
接下来,我还打算通过仅选择高于某个阈值的最大值来优化这个时间列表,即其斜率高于某个限制。 这将使我避免获取每个本地最大值,而是识别最重要的“峰值”。 有人有关于如何做到这一点的建议吗?
3个回答

2
你可以通过对移位后的x数组取差值来找到峰值:
In [14]: x
Out[14]: 
array([ 46.,  25.,  39.,  58.,  89.,  60.,  57.,  60.,  46.,  31.,  66.,
        78.,  49.,  47.,  31.,  55.,  19.,  10.,  31.,  36.,  61.,  29.,
        32.,  49.,  35.,  17.,  22.])

In [15]: x[1:] - x[:-1]
Out[15]: 
array([-21.,  14.,  19.,  31., -29.,  -3.,   3., -14., -15.,  35.,  12.,
       -29.,  -2., -16.,  24., -36.,  -9.,  21.,   5.,  25., -32.,   3.,
        17., -14., -18.,   5.])
< p > x[1:] - x[:-1] 的值给出了x值之间的“斜率”。通过确定这个斜率从正数变为负数的位置,您可以找到原始数组中峰值的索引。 < /p >
In [33]: slope = x[1:] - x[:-1]

In [34]: indices = [i+1 for i in range(len(slope)-1) if slope[i] > 0 and slope[i+1] < 0]

In [35]: indices
Out[35]: [4, 7, 11, 15, 20, 23]

In [36]: [x[j] for j in indices]
Out[36]: [89, 60, 78, 55, 61, 49]

我没有把时间列成列表,但是由于你有索引...


谢谢您的回答。实际上,我正在使用我上面提到的方法scipy.signal中的argrelextrema,如下所示:x = np.array(df_1, dtype=np.float) # for local maxima print argrelextrema(x, np.greater)这给了我数组[4, 7, 11, 15, 20, 23],但是我想返回这些索引所指向的原始数据帧的时间。您有任何想法如何做到这一点吗?先感谢您。 - DK99
将数据框的第一列制作成一个列表(我们称之为d),并对其进行索引:[d[j] for j in indices] - Roland Smith

1
截至SciPy 1.1版本,您也可以使用find_peaks
import numpy as np                    
import matplotlib.pyplot as plt
from scipy.signal import find_peaks 

x = np.array([ 46.,  25.,  39.,  58.,  89.,  60.,  57.,  60.,  46.,  31.,  66.,
        78.,  49.,  47.,  31.,  55.,  19.,  10.,  31.,  36.,  61.,  29.,
        32.,  49.,  35.,  17.,  22.])

peaks, _ = find_peaks(x)

plt.plot(x)
plt.plot(peaks, x[peaks], "x")
plt.show()

这将绘制所有本地极大值:

enter image description here

如果现在你想要使用一个阈值(例如60),你可以使用以下代码(其余代码相同):
peaks, _ = find_peaks(x, height=60)

这将绘制:

enter image description here


0
如果我理解正确的话,你在使用argrelextrema之后所需要做的就是将这些索引应用到时间上。假设你的初始代码段如下:
x = np.array(df_1, dtype=np.float)

# for local maxima
print argrelextrema(x, np.greater)

你所需要做的就是像这样进行修改:

indices = argrelextrema(x, np.greater)
df_1['time'] = df_1.index # to turn your times into a column of a dataframe - they are currently in index, right?

# So your solution is this:
print df_1.ix[indices[0], 'time']  # the [0] is there because argrelextrema returns a tuple of the array of indices and dtype, so the first item of the tuple are the indices themselves

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接