簡體   English   中英

python - 如何查找並在視覺上標記序列的局部最小值?

[英]python - How to find and visually mark the local minima of a sequence?

如何繪制具有增加局部最小值的點序列並用另一種顏色標記它們? 類似於圖片中的東西。 我無法使用該序列設置列表,並且最小值是錯誤的。 或者有沒有更簡單的方法來做到這一點?

情節示例

我試過這個代碼:

import sys
from numpy import NaN, Inf, arange, isscalar, asarray, array
import random
import numpy as np
import matplotlib.pyplot as plt

def peakdet(v, delta, x = None):
    '''
    Converted from MATLAB script at http://billauer.co.il/peakdet.html
    Returns two arrays
    function [maxtab, mintab]=peakdet(v, delta, x)
    '''
    maxtab = []
    mintab = []

    if x is None:
        x = arange(len(v))  
    v = asarray(v)
    if len(v) != len(x):
        sys.exit('Input vectors v and x must have same length')
    if not isscalar(delta):
        sys.exit('Input argument delta must be a scalar')
    if delta <= 0:
        sys.exit('Input argument delta must be positive')

    mn, mx = Inf, -Inf
    mnpos, mxpos = NaN, NaN
    lookformax = True
    for i in arange(len(v)):
        this = v[i]
        if this > mx:
            mx = this
            mxpos = x[i]
        if this < mn:
            mn = this
            mnpos = x[i]
        if lookformax:
            if this < mx-delta:
                maxtab.append((mxpos, mx))
                mn = this
                mnpos = x[i]
                lookformax = False
        else:
            if this > mn+delta:
                mintab.append((mnpos, mn))
                mx = this
                mxpos = x[i]
                lookformax = True
    return array(maxtab), array(mintab)

if __name__=="__main__":
    from matplotlib.pyplot import plot, scatter, show
    series = [7,6,5,4,3,1,3,5,6,9,12,13,10,8,6,3,5,6,7,8,13,15,11,12,9,6,4,8,9,10,15,16,17,19,22,17,15,13,11,10,7,5,8,9,12]
    maxtab, mintab = peakdet(series,.3)
    y = np.linspace(0, 10, len(series))
    plt.plot(y, series, '-', color='black');
#    scatter(array(maxtab)[:,0], array(maxtab)[:,1], color='blue')
    scatter(array(mintab)[:,0], array(mintab)[:,1], color='red')
    show()

我得到了這個數字:

結果圖

嘗試scipy.signal.find_peaks 要找到最小值,您將series乘以 -1。

find_peaks返回峰值或最小值的索引。 要獲得正確的繪圖位置,您必須使用find_peaks的輸出索引xseries

如果您擔心包含遞減最小值序列的信號,您可以使用np.diff比較連續峰值的np.diff

import matplotlib.pyplot as plt
from scipy.signal import find_peaks
import numpy as np

series = np.array([7,6,5,4,3,1,3,5,6,9,12,13,10,8,6,3,5,6,7,8,13,15,11,12,9,6,4,8,9,10,15,16,17,19,22,17,15,13,11,10,7,5,8,9,12])
peaks, _ = find_peaks(series)
mins, _ =find_peaks(series*-1)
x = np.linspace(0, 10, len(series))
plt.plot(x, series, color='black');
plt.plot(x[mins], series[mins], 'x', label='mins')
plt.plot(x[peaks], series[peaks], '*', label='peaks')
plt.legend()

在此處輸入圖片說明

您的原始代碼中有兩個錯誤:

  • 在您的原始版本中,您在plt.plot使用 'o' 作為標記符號。 這畫點。 現在您使用“-”繪制線條更正了它。
  • 您仍然沒有使用與繪制線條相同的x來調用您的peakdet 通過使用不同的x ,散點圖使用不同的 x 位置作為線圖放置。

請參閱@dubbbdan 的答案,以了解您的peakdet函數的良好替代方案。 您需要根據應用程序中的確切值試驗最佳設置。

這是您的原始代碼,但已更正錯誤:

import sys
from numpy import NaN, Inf, arange, isscalar, array
import numpy as np
import matplotlib.pyplot as plt

def peakdet(v, delta, x):
    '''
    Converted from MATLAB script at http://billauer.co.il/peakdet.html
    Returns two arrays
    function [maxtab, mintab]=peakdet(v, delta, x)
    '''
    maxtab = []
    mintab = []
    if len(v) != len(x):
        sys.exit('Input vectors v and x must have same length')
    if not isscalar(delta):
        sys.exit('Input argument delta must be a scalar')
    if delta <= 0:
        sys.exit('Input argument delta must be positive')

    mn, mx = Inf, -Inf
    mnpos, mxpos = NaN, NaN
    lookformax = True

    for i in arange(len(v)):
        this = v[i]
        if this > mx:
            mx = this
            mxpos = x[i]
        if this < mn:
            mn = this
            mnpos = x[i]

        if lookformax:
            if this < mx-delta:
                maxtab.append((mxpos, mx))
                mn = this
                mnpos = x[i]
                lookformax = False
        else:
            if this > mn+delta:
                mintab.append((mnpos, mn))
                mx = this
                mxpos = x[i]
                lookformax = True
    return array(maxtab), array(mintab)

series = [7,6,5,4,3,1,3,5,6,9,12,13,10,8,6,3,5,6,7,8,13,15,11,12,9,6,4,8,9,10,15,16,17,19,22,17,15,13,11,10,7,5,8,9,12]
x = np.linspace(0, 10, len(series))
maxtab, mintab = peakdet(series, .3, x)   # it is very important to give the correct x to `peakdet`
plt.plot(x, series, '-', color='black')   # use the same x for plotting
plt.scatter(maxtab[:,0], maxtab[:,1], color='blue') # the x-coordinates used in maxtab need to be the same as those in plot
plt.scatter(mintab[:,0], mintab[:,1], color='red')
plt.show()

這情節: 結果圖

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM