Нахождение локального минимума между двумя пиками

У меня есть некоторые данные временных рядов в Pandas, где мне нужно извлечь определенные локальные минимумы из столбца, чтобы я мог использовать их в качестве функций в модели LSTM. Чтобы визуализировать то, что я ищу, я приложил Изображение, где обведено точки - это значения, которые я хочу найти.

Другие красные точки, которые вы видите внизу графика, — это моя неудачная попытка использовать argrelextrema со следующим кодом:

#Trying to Locate Minimum Values
df['HKL Min'] = df.iloc[argrelextrema(df.hkla.values, np.less_equal,order=50)[0]]['hkla']

#Plotting a range of values from dataset:
sns.lineplot(x=df.index[0:3000], y= 'hkla', data=df[0:3000], label='Hookload');
sns.scatterplot(x=df.index[0:3000], y= 'HKL Min', data=df[0:3000], s= 50, color ='red', label='HKL Min');

Как вы могли заметить, данные в моем столбце имеют повторяющийся шаблон, и точки, которые я хочу найти, являются минимумами, найденными между двумя парами пиков. Существуют ли в Python какие-либо функции, которые могут помочь мне найти эти конкретные точки? Любая форма помощи будет высоко оценена. Я также открыт для других предложений, которые могут решить мою проблему здесь...


person W1nu    schedule 28.04.2021    source источник
comment
Привет и добро пожаловать на SO. Было бы здорово, если бы вы могли ознакомиться с как спросить, а затем попытаться создать макве.   -  person rpanai    schedule 28.04.2021
comment
Размещение некоторых образцов данных было бы очень полезно здесь   -  person perl    schedule 28.04.2021
comment
Я не помню, чтобы в Numpy или Scipy были встроенные методы. Тем не менее, вы должны научиться кодировать это, потому что оно будет встречаться много раз. Вы можете сделать это самостоятельно, используя тесты 1-й и 2-й производной, или найти фильтр Савицкого-Голея.   -  person wbg    schedule 29.04.2021
comment
@perl Мои наборы данных являются конфиденциальными, поэтому я не публиковал образцы данных, приношу извинения за неудобства.   -  person W1nu    schedule 29.04.2021
comment
@wbg Я новичок в Python, поэтому я попросил быстро исправить. Попробую и ваши рекомендованные методы.   -  person W1nu    schedule 29.04.2021
comment
@ W1nu Это нормально, но обычно вы можете взять небольшую выборку + запутать данные (сбросить даты до 1900-01-01, нормализовать значения и т. данные   -  person perl    schedule 29.04.2021


Ответы (2)


Вы можете сделать что-то подобное с вашими данными:

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from scipy.signal import argrelextrema


np.random.seed(1234)
rs = np.random.randn(500)
xs = [0]
for r in rs:
    xs.append(xs[-1] * 0.999 + r)
df = pd.DataFrame(xs, columns=['point'])

что дает эти данные

point
0    0.000000
1    0.471435
2   -0.720012
3    0.713415
4    0.400050
..        ...
496  3.176240
497  3.007734
498  3.123841
499  1.045736
500  0.041935

[501 rows x 1 columns]

Вы можете выбрать, как часто вы хотите отмечать локальную ма или мин, играя с параметром:

n = 10

df['min'] = df.iloc[argrelextrema(df.point.values, np.less_equal,
                    order=n)[0]]['point']
df['max'] = df.iloc[argrelextrema(df.point.values, np.greater_equal,
                    order=n)[0]]['point']


plt.scatter(df.index, df['min'], c='r')
plt.scatter(df.index, df['max'], c='r')
plt.plot(df.index, df['point'])
plt.show()

Который дает:

введите здесь описание изображения

Другой вариант для n может быть (и все зависит от того, что вы хотите):

n = 40

df['min'] = df.iloc[argrelextrema(df.point.values, np.less_equal,
                    order=n)[0]]['point']
df['max'] = df.iloc[argrelextrema(df.point.values, np.greater_equal,
                    order=n)[0]]['point']


plt.scatter(df.index, df['min'], c='r')
plt.scatter(df.index, df['max'], c='g')
plt.plot(df.index, df['point'])
plt.show()

введите здесь описание изображения

Чтобы получить разметку, для каких точек на самом деле max и min, вы можете сделать новый df:

new_df = pd.DataFrame(np.where(df.T == df.T.max(), 1, 0),index=df.columns).T

который дает информацию о том, какая строка в df является максимальной или минимальной. В противном случае исходный df содержит эту информацию в созданных столбцах min и max, те экземпляры, которые не являются nan

EDIT: поиск пиков выше порогового значения

Если вас интересуют пики выше определенного значения, вам следует использовать find_peaks следующим образом:

from scipy.signal import find_peaks 
peaks, _ = find_peaks(df['point'], height = 15)
plt.plot(df['point'])
plt.plot(peaks, df['point'][peaks], "x")
plt.show()

который будет производить:

peaks,_


(array([304, 309, 314, 317, 324, 329, 333, 337, 343, 349, 352, 363, 366,
        369, 372, 374, 377, 379, 381, 383, 385, 387, 391, 394, 397, 400,
        403, 410, 413, 418, 424, 427, 430, 433, 436, 439, 442, 444, 448],
       dtype=int64),
 {'peak_heights': array([15.68868141, 15.97184882, 15.04790966, 15.6146908 , 16.49191501,
         18.0852033 , 18.11467247, 19.48469432, 21.32391722, 19.90407526,
         19.93683051, 24.40980129, 28.00319793, 26.1080406 , 24.44322213,
         23.16993982, 22.27505873, 21.47500832, 22.3236231 , 24.02484906,
         23.83727054, 24.32609486, 21.25365717, 21.10295203, 20.03162979,
         20.64021444, 19.78510855, 21.62624829, 22.34904425, 21.60431638,
         18.41968769, 18.24153961, 18.00747871, 18.02793964, 16.72552016,
         17.58573207, 16.90982675, 16.9905686 , 16.30563852])})

и графически введите здесь описание изображения

person Serge de Gosson de Varennes    schedule 29.04.2021
comment
это примерно то, что я ищу. Можно ли использовать argrelextrema только для определенной высоты? Если я использую ваш пример, есть ли способ найти только пики, где значения y > 15? - person W1nu; 29.04.2021
comment
Смотрите мое редактирование, которое отвечает на ваш вопрос. - person Serge de Gosson de Varennes; 30.04.2021

Я смог решить свою проблему, используя подход, предоставленный @Serge de Gosson de Varennes. Я отключил argrelextrema с помощью scipy find_peaks() следующим образом:

df['Min'] = df.iloc[find_peaks(-df.column[0:3000], height=(-350000,-250000), threshold = None,
                           distance=200, )[0]]['column']

Ввод высоты здесь дал мне возможность выбрать интервал в направлении y, что упростило обнаружение локальных минимумов, которые я искал в указанном интервале. При построении результатов следующим образом:

plt.plot(df.index[0:3000], df.column[0:3000])
plt.plot(df.index, df['Min'],'ro', color = 'red', label = 'Min Values')

Я получил следующий график

Спасибо за помощь!

person W1nu    schedule 29.04.2021