Je pense qu'il est difficile de répondre à ce problème en général, car il existe des ensembles de données pour lesquels une solution pourrait fonctionner, et d'autres pour lesquels elle ne fonctionne pas. Vos données sont à l'envers, donc la première étape consiste à inverser y
à -y
Ainsi, les minimums seront interprétés comme des maximums (et prendront peut-être la valeur absolue pour éviter de traiter les nombres négatifs).
La première option consiste à utiliser scipy.signal.find_peaks
. En connaissant vos données, vous pouvez utiliser certains des paramètres : d'après mon expérience, la hauteur, la distance et la proéminence sont les plus utiles. Il y a une bonne explication sur les paramètres de find_peaks
. Cette méthode permet d'identifier correctement les pics dans la plupart des cas, mais nécessite du temps pour définir les arguments de manière appropriée.
Une solution similaire avec scipy.signal.find_peaks_cwt
Dans ce cas (dans la plupart des cas), vous devrez ajuster le paramètre widths, qui est (d'après la documentation) :
Tableau 1-D des largeurs à utiliser pour le calcul de la matrice CWT. En général, cette plage doit couvrir la largeur attendue des pics d'intérêt.
Mais là encore, cela nécessite une certaine connaissance préalable de vos données.
Comme vous avez des données périodiques, vous pouvez peut-être utiliser la FFT pour trouver les fréquences caractéristiques et ajuster les paramètres à l'intérieur. find_peaks
et find_peaks_cwt
. Comme vous n'avez pas fourni l'ensemble des données, je n'ai que des données synthétiques à traiter. Notez que je renvoie len(peaks) - 1
parce qu'en général, sur les frontières, il y a une période supplémentaire qui est comptée.
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)