Python,找到数组的所有局部最大值,调整测量中的缺陷 [英] Python, finding all local maxima of array, adjusting for flaws in measurement

查看:384
本文介绍了Python,找到数组的所有局部最大值,调整测量中的缺陷的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试获取一维数组中的最大点,在该数组中它可以绘制多条曲线.为此,我使用scipy.signal.argrelextremanp.greater.在此处给出数组为y的位置:

i'm trying to get the maximum points in a one dimensional array, where it makes several curves. To do this i use scipy.signal.argrelextrema, along with np.greater. Give here where the array is y:

argrelextrema(y, np.greater)

问题在于,由于收集y数据的方式,此一维数据具有不准确性.因此,曲线的底部有很多误报",从技术上讲,由于一个值​​大于周围的值,因此在底部有一个最大值.

The issue is, that this one dimensional data has inaccuracies due to the way the data for y was gathered. And so, there's a lot of "false positives" at the bottom of the curve, where there technically is a maxima at the bottom because of one value being bigger than the surrounding ones.

作为参考,这里是x上方的y,y只是每个y值的索引,以演示我正在使用的数组.底部的错误是不可见的.忽略轴,使用我在代码中拥有的东西.

For reference, here's y, over x which is just the index of each y value, to demonstrate the array i'm working with. The inaccuracies at the bottom is not visible. Ignore axises, used what i had in the code.

此外,这也是我使用找到的最大值来计算值的结果,这是不希望的,因为预期结果应该是一条平滑的下降曲线.该图以每个点的一个点递增的顺序绘制而成.正如从实际图表中可以观察到的那样,这显然是错误的.

Also, here's the result of me using the found maxima to calculate a value, as seen this is not wanted, as the expected result should have been a smooth falling curve. The graph was made with one point for each maxima, in an increasing order. And it's clearly wrong, as one can observe from the actual graph.

那么,避免shis的最佳解决方案是什么?我找不到能够以一种足够好的方式近似于该图的东西,使我能够使用它.我研究了平滑处理,但是发现的方法(例如scipy.signal中的savgol_filter)是我无法理解的.

So, what's the best solution to avoid shis? I failed to find something that could approximate the graph in a good enough manner for me the be able to use it. I looked into smoothening, but the methods i found, like savgol_filter from scipy.signal, was something i could not understand.

当前的解决方案是忽略小于5的y值,该值大约在曲线的底部,但是根本不是理想的解决方案.

The current solution was to ignore values of y that were below 5, which was roughly a bit over the bottom of the curve, but not an ideal solution at all.

更新:

scipy.signal发现的find_peaks_cwt也适用于此.这有点复杂,因为我一点也不知道它的大部分工作原理,即使在稍加阅读之后也是如此.但是,我使用以下方法设法制作出了更好的图形:find_peaks_cwt(y, [3], noise_perc=2)但是,下面看到的结果只是由于我将噪声从10降低到2的结果,而不真正知道这会如何影响结果.

Found out find_peaks_cwt from scipy.signal works for this too. It's a tad more complex as i have absolutely no clue how most of it works, even after reading up on it a bit. However, i managed to make a slightly better graph, i think, using: find_peaks_cwt(y, [3], noise_perc=2) However, the result seen below, is only a result of me dropping noise from 10 to 2, without really knowing how that affects the result.

这是我正在处理的一维数组: https://pastebin.com/GZrBBRce 对不起,表示不好,但是每一行都是列表中的下一个值.有点大

Here's is the 1D-array i'm working on: https://pastebin.com/GZrBBRce Sorry for bad representation, but each line is the next value in the list. It's a bit large.

最小工作示例m,y来自pastebin,有点大,可以包含在最小工作示例中:

Minimum working examplem, y is from the pastebin, a bit large to include in minimum working example:

energy = []
for i in find_peaks_cwt(y, [3],noise_perc=2):
    energy.append(y[i])
plt.plot([i for i in range(len(energy))], energy)
plt.show()

这是通过一些猜测得出的,结果可以在该问题的最后一张图片中看到.

This was made with some guessing, and the result is seen in the last image in this question.

更新2:进一步的进展是,我使用numpy.polyfit平滑了15度,从而平滑了y函数.它出奇的准确.并且由于这很顺利,所以我可以恢复到第一个函数argrelextrema(y, np.greater),它为我提供了相当不错的答案,并且不包括误报,如上图所示. (当我的图形中只有20个以上时,我有30-40个最大值.)

Update 2: Further progress, i smoothed out the y function using numpy.polyfit with a 15 degree approximation. It's surprisingly accurate. And since that is smooth, i can revert to the first function argrelextrema(y, np.greater), and it's gives me a pretty decent answer as well as not including false positives, as seen in the above graphs. (I got 30-40 maximas, when my graph only has a little above 20 of them.)

在解决标记问题之前,我会稍作停留,以防有人想寻求更好的解决方案并使用numpy.polyfit逼近图形.但是,这解决了我的用例的问题.

I'll let it stand a bit, before marking solved, in case anyone want to have a go at a better solution and approximating the graph with numpy.polyfit. However this solved the issue for my usecase.

推荐答案

我会使用:scipy.signal.find_peaks_cwt().

从其文档中:

试图在一维阵列中找到峰.

Attempt to find the peaks in a 1-D array.

一般方法是通过将矢量与每个宽度的wavelet(width)卷积来平滑向量.可接受以足够长的尺度出现并具有足够高的SNR的相对最大值.

The general approach is to smooth vector by convolving it with wavelet(width) for each width in widths. Relative maxima which appear at enough length scales, and with sufficiently high SNR, are accepted.

更新(包含实际数据)

import numpy as np
import scipy as sp

import matplotlib.pyplot as plt

import scipy.signal

y_arr = np.loadtxt('/home/raid1/metere/Downloads/1d_array.txt')
print('array size: ', y_arr.shape)

arr_size = len(y_arr)
expected_num = 30

expected_width = arr_size // expected_num // 2
print('expected width of peaks: ', expected_width)

peaks = sp.signal.find_peaks_cwt(y_arr, np.linspace(2, expected_width, 10))

print('num peaks: ', len(peaks))
print('peaks: ', peaks)

plt.plot(y_arr)
for peak in peaks:
    plt.axvline(peak)
plt.show()

这可能需要进一步调整,例如,以提高准确性.

This can probably tweaked further, for example to increase the accuracy.

这篇关于Python,找到数组的所有局部最大值,调整测量中的缺陷的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆