I want to detect max and min of a time series, always looking on the left side. Looking right would be looking in the future since it's analyzed in live. My method:
- When increasing, you update the variable
max
- When decreasing, you update the variable
min
- Then, when decreasing, if the value is inferior to 50% of
(max - min)
, you consider that you are defining a new low - And vise versa when increasing
It translates like this:
import pandas as pd
timerange = pd.date_range(start='1/1/2018', end='1/31/2018')
data = [0, 1, 2, 3, 4, 2, 1, 0, -1, 0, 3, 2, 1, 1, 0.5, 0, 1, 2, 4, 5, 6, 7, 8, 4, -2, -4, 0, 5, 3, 2, 0]
timeseries = pd.DataFrame(index=timerange, data=data, columns=['Value'])
max = data[0]
min = data[0]
pct = .5
tendancy = False
for now in timeseries.index:
value = timeseries.loc[now, 'Value']
if value >= max:
max = value
if value <= min:
min = value
range = max-min
# Cancel the previous max value when going up if the 50% rule is triggered
if value >= min + range * pct and tendancy != 'up':
tendancy = 'up'
max = value
# Cancel the previous min value when going down if the 50% rule is triggered
elif value <= max - range * pct and tendancy != 'down':
tendancy = 'down'
min = value
ratio = (value-min)/(max-min)
timeseries.loc[now, 'Max'] = max
timeseries.loc[now, 'Min'] = min
timeseries.loc[now, 'Ratio'] = ratio
timeseries[['Value', 'Min', 'Max']].plot()
timeseries['Ratio'].plot(secondary_y=True)
It works as expected and as a result, looking at the Ratio
variable, you know if you are currently defining a new low (0) or a new high (1), whatever the amplitude or the frequency of the signal.
However, on my real data (~200 000 rows), it is super long. I was wondering if there is a way to optimize this, especially using the .apply()
method of DataFrame. But since results depend on the previous row, I don't know if this method is applicable.