Я думаю, что на эту проблему сложно ответить в целом, потому что есть наборы данных, где решение может работать, а есть наборы данных, где это не работает. Ваши данные перевернуты, поэтому первый шаг - это перевернуть y
на -y
, поэтому минимальные значения будут интерпретироваться как максимумы (и, возможно, принимать абсолютное значение, чтобы избежать отрицательных чисел).
Первый вариант - использовать scipy.signal.find_peaks
. Зная свои данные здесь, вы можете использовать некоторые параметры: по моему опыту, рост, расстояние и известность являются наиболее полезными. Есть красивое объяснение о параметрах find_peaks
. Это позволит правильно определить пики в большинстве случаев, но требует времени для соответствующей установки аргументов.
Аналогичное решение с scipy.signal.find_peaks_cwt
, здесь (в большинстве случаев) вам нужно будет отрегулировать параметр ширины, который (из документации):
1-мерный массив ширины, используемый для вычисления матрицы CWT. В общем, этот диапазон должен охватывать ожидаемую ширину интересующих пиков.
Но опять же, это требует некоторых предварительных знаний о ваших данных.
Поскольку у вас есть периодi c данные , может быть, вы можете использовать БПФ, чтобы найти характеристики c частот, чтобы настроить параметры внутри find_peaks
и find_peaks_cwt
. Поскольку вы не предоставили набор данных, у меня есть только синтетические c данные. Обратите внимание, что я возвращаю 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)