寻找两个峰之间的局部最小值
Finding local minimum between two peaks
我在 Pandas 中有一些时间序列数据,我需要从列中提取特定的局部最小值,以便将它们用作 LSTM 模型中的特征。为了可视化我正在寻找的内容,我附上了一个 Picture,其中带圆圈的点是我希望找到的值。
您在图表底部看到的其他红点是我尝试通过以下代码使用“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 中是否有一些现有函数可以帮我定位这些具体点?任何形式的帮助将不胜感激。我也愿意接受其他可以解决我的问题的建议...
你可以用你的数据做这样的事情:
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]
您可以通过使用参数来选择要标记本地 ma 或 min 的频率:
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()
要标记哪些点实际上在最大值和最小值的位置,您可以创建一个新的 df:
new_df = pd.DataFrame(np.where(df.T == df.T.max(), 1, 0),index=df.columns).T
它给出了关于 df
中哪一行是最大值或最小值的信息。否则,原始 df
在创建的 min
和 max
列中包含该信息,这些实例不是 nan
编辑:查找高于阈值的峰值
如果您对某个值以上的峰值感兴趣,那么您应该按以下方式使用 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])})
和图形化
我能够使用@Serge de Gosson de Varennes 提供的方法解决我的问题。我用 scipy “find_peaks()” 关闭了“argrelextrema”,如下所示:
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')
我得到了以下graph
感谢您的协助!
我在 Pandas 中有一些时间序列数据,我需要从列中提取特定的局部最小值,以便将它们用作 LSTM 模型中的特征。为了可视化我正在寻找的内容,我附上了一个 Picture,其中带圆圈的点是我希望找到的值。
您在图表底部看到的其他红点是我尝试通过以下代码使用“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 中是否有一些现有函数可以帮我定位这些具体点?任何形式的帮助将不胜感激。我也愿意接受其他可以解决我的问题的建议...
你可以用你的数据做这样的事情:
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]
您可以通过使用参数来选择要标记本地 ma 或 min 的频率:
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()
要标记哪些点实际上在最大值和最小值的位置,您可以创建一个新的 df:
new_df = pd.DataFrame(np.where(df.T == df.T.max(), 1, 0),index=df.columns).T
它给出了关于 df
中哪一行是最大值或最小值的信息。否则,原始 df
在创建的 min
和 max
列中包含该信息,这些实例不是 nan
编辑:查找高于阈值的峰值
如果您对某个值以上的峰值感兴趣,那么您应该按以下方式使用 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])})
和图形化
我能够使用@Serge de Gosson de Varennes 提供的方法解决我的问题。我用 scipy “find_peaks()” 关闭了“argrelextrema”,如下所示:
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')
我得到了以下graph
感谢您的协助!