我认为一般来说这是一个很难回答的问题,因为有些数据集可以解决方案,而有些数据集则不能。你的数据是倒置的,所以第一步是将y翻转到-y,所以最小值将被解释为最大值(并且可能取绝对值以避免处理负数。)
第一个选项是使用scipy.signal.find_peaks。在这里了解您的数据,您可以利用一些参数:根据我的经验,高度、距离和突出度是最有用的。
There is a nice explanation关于find_peaks的参数。
在大多数情况下,这将正确识别峰值,但需要时间来适当地设置参数。
与scipy.signal.find_peaks_cwt 类似的解决方案,在这里(在大多数情况下)您需要调整宽度参数,即(来自文档):
用于计算 CWT 矩阵的一维宽度数组。一般来说,
此范围应涵盖目标峰的预期宽度。
但同样,这需要对您的数据有一些先验知识。
因为你有周期性数据,也许你可以利用FFT找到特征频率来调整find_peaks和find_peaks_cwt里面的参数。由于您没有提供数据集,因此我只有合成数据要处理。请注意,我返回len(peaks) - 1,因为通常在边界上会有一个额外的时间段被计算在内。
import numpy as np
from scipy.signal import find_peaks, find_peaks_cwt
import matplotlib.pyplot as plt
# some generic data
x = np.linspace(0, 1000, 10000)
y = 250 + 100 * np.sin(0.08 * x) - np.random.normal(30, 20, 10000)
def count_waves_1(x, y):
peaks, props = find_peaks(y, prominence=120, height= np.max(y) / 10, distance=200)
# here you can make use of props to filter the peaks by different properties,
# for example extract only the n largest prominence peak:
#
# ind = np.argpartition(props["prominences"], -n_largest)[-n_largest:]
# peaks = peaks[ind]
plt.plot(x, y)
plt.plot(x[peaks], y[peaks], 'ro')
return len(peaks) - 1
first_solution = count_waves_1(x, y)
def count_waves_2(x, y):
peaks = find_peaks_cwt(y, widths=np.arange(100, 200))
plt.plot(x, y)
plt.plot(x[peaks], y[peaks], 'ro')
return len(peaks) - 1
second_solution = count_waves_2(x, y)
print(first_solution, second_solution)