• 1000 . Используя то, что мне сказал @ user58697, мне удалось создать код, который обнаруживает каждый пик между порогом.
Используя logi c, который он объяснил if ((flow[i+1] - flow[i]) / (time[i+1] - time[i]) > threshold
, я закодировал следующий код:
Началось с чтения .csv
и анализа дат с последующим разделением на два массива numpy:
dataset = pd.read_csv('https://raw.githubusercontent.com/MigasTigas/peak_removal/master/dataset_simple_example.csv', parse_dates=['date'])
dataset = dataset.sort_values(by=['date']).reset_index(drop=True).to_numpy() # Sort and convert to numpy array
# Split into 2 arrays
values = [float(i[1]) for i in dataset] # Flow values, in float
values = np.array(values)
dates = [i[0].to_pydatetime() for i in dataset]
dates = np.array(dates)
Затем применил (flow[i+1] - flow[i]) / (time[i+1] - time[i])
ко всему набору данных:
flow = np.diff(values)
time = np.diff(dates).tolist()
time = np.divide(time, np.power(10, 9))
slopes = np.divide(flow, time) # (flow[i+1] - flow[i]) / (time[i+1] - time[i])
slopes = np.insert(slopes, 0, 0, axis=0) # Since we "lose" the first index, this one is 0, just for alignments
И, наконец, для обнаружения пиков мы сократили данные до windows по x
секунд каждый. Таким образом, мы можем легко их обнаружить:
# ROLLING WINDOW
size = len(dataset)
rolling_window = []
rolling_window_indexes = []
RW = []
RWi = []
window_size = 240 # Seconds
dates = [i.to_pydatetime() for i in dataset['date']]
dates = np.array(dates)
# create the rollings windows
for line in range(size):
limit_stamp = dates[line] + datetime.timedelta(seconds=window_size)
for subline in range(line, size, 1):
if dates[subline] <= limit_stamp:
rolling_window.append(slopes[subline]) # Values of the slopes
rolling_window_indexes.append(subline) # Indexes of the respective values
else:
RW.append(rolling_window)
if line != size: # To prevent clearing the last rolling window
rolling_window = []
RWi.append(rolling_window_indexes)
if line != size:
rolling_window_indexes = []
break
else:
# To get the last rolling window since it breaks before append
RW.append(rolling_window)
RWi.append(rolling_window_indexes)
После того, как все прокатилось windows мы начинаем веселье:
t = 0.3 # Threshold
peaks = []
for index, rollWin in enumerate(RW):
if rollWin[0] > t: # If the first value is greater of threshold
top = rollWin[0] # Sets as a possible peak
bottom = np.min(rollWin) # Finds the minimum of the peak
if bottom < -t: # If less than the negative threshold
bottomIndex = int(np.argmin(rollWin)) # Find it's index
for peak in range(0, bottomIndex, 1): # Appends all points between the first index of the rolling window until the bottomIndex
peaks.append(RWi[index][peak])
Идея этого кода заключается в том, что каждый пик имеет подъем и падение, и если оба превышают заявленный порог, то это пик выброса вместе со всеми пиками между ними:
![enter image description here](https://i.stack.imgur.com/WqvjX.png)
![enter image description here](https://i.stack.imgur.com/FBUkW.png)
Where translated to the real dataset used, posted on github :
введите описание изображения здесь