J'ai des données de série temporelle. Génération de données
date_rng = pd.date_range('2019-01-01', freq='s', periods=400)
df = pd.DataFrame(np.random.lognormal(.005, .5,size=(len(date_rng), 3)),
columns=['data1', 'data2', 'data3'],
index= date_rng)
s = df['data1']
Je veux créer une ligne en zig-zag reliant entre les maxima locaux et les minima locaux, qui satisfait la condition selon laquelle sur l'axe des y, |highest - lowest value|
chaque ligne en zig-zag doit dépasser un pourcentage (disons 20%) de la distance de la précédente ligne en zig-zag ET une valeur prédéterminée k (disons 1.2)
Je peux trouver les extrema locaux en utilisant ce code:
# Find peaks(max).
peak_indexes = signal.argrelextrema(s.values, np.greater)
peak_indexes = peak_indexes[0]
# Find valleys(min).
valley_indexes = signal.argrelextrema(s.values, np.less)
valley_indexes = valley_indexes[0]
# Merge peaks and valleys data points using pandas.
df_peaks = pd.DataFrame({'date': s.index[peak_indexes], 'zigzag_y': s[peak_indexes]})
df_valleys = pd.DataFrame({'date': s.index[valley_indexes], 'zigzag_y': s[valley_indexes]})
df_peaks_valleys = pd.concat([df_peaks, df_valleys], axis=0, ignore_index=True, sort=True)
# Sort peak and valley datapoints by date.
df_peaks_valleys = df_peaks_valleys.sort_values(by=['date'])
mais je ne sais pas comment lui appliquer la condition de seuil. Veuillez me conseiller sur la façon d'appliquer une telle condition.
Étant donné que les données peuvent contenir des millions d'horodatages, un calcul efficace est fortement recommandé
Pour une description plus claire:
Exemple de sortie, à partir de mes données:
# Instantiate axes.
(fig, ax) = plt.subplots()
# Plot zigzag trendline.
ax.plot(df_peaks_valleys['date'].values, df_peaks_valleys['zigzag_y'].values,
color='red', label="Zigzag")
# Plot original line.
ax.plot(s.index, s, linestyle='dashed', color='black', label="Org. line", linewidth=1)
# Format time.
ax.xaxis_date()
ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d"))
plt.gcf().autofmt_xdate() # Beautify the x-labels
plt.autoscale(tight=True)
plt.legend(loc='best')
plt.grid(True, linestyle='dashed')
Ma sortie souhaitée (quelque chose de similaire à cela, le zigzag ne connecte que les segments significatifs)