我写了一个代码来查找时间序列中的峰值,我希望它也可以绘制本地基线.目前我正在使用由两个cosinusoids构建的测试时间序列.
代码如下,其中p_times是峰值中心的时间:
step = 0.1
time = np.arange(0, 10.1, step)
#Does stuff to find peaks
p_times = [0.9, 1., 1.1, 1.9, 2., 2.1, 2.9, 3., 3.1, 3.9, 4., 4.1, 4.9, 5., 5.1, 5.9, 6., 6.1, 6.9, 7., 7.1, 7.9, 8., 8.1, 8.9, 9., 9.1]
idx = np.array([np.where(time == x)[0][0] for x in p_times])
Run Code Online (Sandbox Code Playgroud)
最后一条指令应该给出一个数组,其中包含与峰值对应的时间元素的索引,但我得到:
IndexError: index 0 is out of bounds for axis 0 with size 0
Run Code Online (Sandbox Code Playgroud)
这个案例的好奇之处在于将cosinusoids参数更改为看似"幸运"的值,峰值的位置也会发生变化,代码可以正常工作:
p_times = [0.5, 1., 1.5, 2., 2.5, 3., 3.5, 4., 4.5, 5., 5.5, 6., 6.5, 7., 7.5, 8., 8.5, 9., 9.5]
# result: idx = [ 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95]
Run Code Online (Sandbox Code Playgroud)
更新:再次使用"不吉利"的时间序列,我有这个高峰时间阵列:
p_times = [0.3, 1.8, 1.9, 2., 2.1, 2.2, 3.7, 3.8, 3.9, 4., 4.1, 4.2, 4.3, 5.8, 5.9, 6., 6.1, 6.2, 7.7, 7.8, 7.9, 8., 8.1, 8.2, 8.3]
Run Code Online (Sandbox Code Playgroud)
和指示:
idx_c = np.array([np.where(np.isclose(time, x))[0][0] for x in p_times])
Run Code Online (Sandbox Code Playgroud)
再次失败:
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-1-4c7f86bac90c> in <module>()
53 #Baseline extremes (x,y), left and right
54 #idx_c = np.array([np.where(time == x)[0][0] for x in O[:,0]]) #Cannot manage to vectorize this
---> 55 idx_c = np.array([np.where(np.isclose(time, x))[0][0] for x in p_times])
56 print("idx_c = ", idx_c)
57 idx_l = np.array(idx_c - k) #Left extreme is at index of center (peak) minus k positions.
<ipython-input-1-4c7f86bac90c> in <listcomp>(.0)
53 #Baseline extremes (x,y), left and right
54 #idx_c = np.array([np.where(time == x)[0][0] for x in O[:,0]]) #Cannot manage to vectorize this
---> 55 idx_c = np.array([np.where(np.isclose(time, x))[0][0] for x in p_times])
56 print("idx_c = ", idx_c)
57 idx_l = np.array(idx_c - k) #Left extreme is at index of center (peak) minus k positions.
IndexError: index 0 is out of bounds for axis 0 with size 0
Run Code Online (Sandbox Code Playgroud)
这种行为的原因是什么?
您的方法的主要问题是您正在准确地比较浮点值.由于舍入错误,这几乎总是一个非常糟糕的主意,在这个臭名昭着的例子中证明:
>>> 0.1 + 0.2 == 0.3
False
Run Code Online (Sandbox Code Playgroud)
请注意,numpy double和本机python双打基本相似(在任何一种情况下,我都不确定大小依赖于体系结构,但你可能得到我的观点).
首先,您应该始终使用np.isclose/ np.allclose来比较浮点数是否相等.其次,这就是我发布完整答案的原因:你不必使用列表理解,你可以在一个numpy广播呼叫中做你想要的isclose:
>>> idx, data_idx = np.isclose(time[:,None], p_times).nonzero()
>>> idx
array([ 9, 10, 11, 19, 20, 21, 29, 30, 31, 39, 40, 41, 49, 50, 51, 59, 60,
61, 69, 70, 71, 79, 80, 81, 89, 90, 91])
Run Code Online (Sandbox Code Playgroud)
这里发生的是time通过注入尾随单例维度将数组转换为2d列数组,并通过将每个time点与每个p_times点配对来构建bool矩阵.最后一次调用nonzero()返回True值的索引:第一个输出idx包含您正在寻找的索引.
此方法也更安全,因为如果峰值没有匹配时间,它将不会抛出异常.相反,你的idx价值比p_times积分少.在这种情况下,您将能够用于data_idx定位实际找到的峰的索引:
>>> data_idx
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
102 次 |
| 最近记录: |