Tengo datos de una serie temporal. Generando datos
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']
Quiero crear una línea en zig-zag que conecte entre los máximos locales y los mínimos locales, que satisfaga la condición de que en el eje y, |highest - lowest value|
de cada línea en zig-zag debe exceder un porcentaje (digamos 20%) de la distancia de la anterior línea en zig-zag, Y un valor preestablecido k (digamos 1.2)
Puedo encontrar los extremos locales usando este código:
# 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'])
pero no sé cómo aplicarle la condición de umbral. Por favor, avísenme sobre cómo aplicar tal condición.
Como los datos pueden contener millones de marcas de tiempo, se recomienda un cálculo eficiente
Para una descripción más clara:
Ejemplo de salida, de mis datos:
# 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')
Mi salida deseada (algo similar a esto, el zigzag solo conecta los segmentos significativos)