ค้นหา local maxima / minima ด้วย Numpy ในอาร์เรย์ 1D numpy


116

คุณช่วยแนะนำฟังก์ชันโมดูลจาก numpy / scipy ที่สามารถค้นหา local maxima / minima ในอาร์เรย์ 1D numpy ได้หรือไม่ เห็นได้ชัดว่าวิธีการที่ง่ายที่สุดคือการดูเพื่อนบ้านที่ใกล้ที่สุด แต่ฉันต้องการวิธีแก้ปัญหาที่เป็นที่ยอมรับซึ่งเป็นส่วนหนึ่งของ numpy distro



1
ไม่ใช่ใน 2D (ฉันกำลังพูดถึง 1D) และเกี่ยวข้องกับฟังก์ชันที่กำหนดเอง ฉันมีการใช้งานง่าย ๆ ของตัวเอง แต่ฉันสงสัยว่ามีโมดูลที่ดีกว่าที่มาพร้อมกับโมดูล Numpy / Scipy หรือไม่
Navi

บางทีคุณอาจอัปเดตคำถามเพื่อรวมว่า (1) คุณมีอาร์เรย์ 1d และ (2) ประเภทของค่าต่ำสุดในท้องถิ่นที่คุณกำลังมองหา แค่รายการเล็กกว่าสองรายการที่อยู่ติดกัน?
Sven Marnach

1
คุณสามารถดูได้ที่ scipy.signal.find_peaks_cwt หากคุณกำลังพูดถึงข้อมูลที่มีเสียงรบกวน
Lakshay Garg

คำตอบ:


66

หากคุณกำลังมองหารายการทั้งหมดในอาร์เรย์ 1d ที่aมีขนาดเล็กกว่าเพื่อนบ้านคุณสามารถลองได้

numpy.r_[True, a[1:] < a[:-1]] & numpy.r_[a[:-1] < a[1:], True]

นอกจากนี้คุณยังสามารถเรียบnumpy.convolve()อาร์เรย์ของคุณก่อนขั้นตอนนี้ใช้

ฉันไม่คิดว่าจะมีฟังก์ชันเฉพาะสำหรับสิ่งนี้


อืมทำไมต้องเนียนด้วย? เพื่อลบเสียงรบกวน? ฟังดูน่าสนใจ สำหรับฉันแล้วดูเหมือนว่าฉันสามารถใช้จำนวนเต็มอื่นแทน 1 ในโค้ดตัวอย่างของคุณได้ ฉันยังคิดคำนวณการไล่ระดับสี อย่างไรก็ตามถ้าไม่มีฟังก์ชั่นที่แย่กว่านั้น
Navi

1
@Navi: ปัญหาคือแนวความคิดของ "ขั้นต่ำในพื้นที่" แตกต่างกันอย่างมากจากกรณีการใช้งานไปจนถึงกรณีการใช้งานดังนั้นจึงยากที่จะจัดเตรียมฟังก์ชัน "มาตรฐาน" สำหรับวัตถุประสงค์นี้ การทำให้เรียบช่วยให้คำนึงถึงมากกว่าเพื่อนบ้านที่ใกล้ที่สุด การใช้จำนวนเต็มอื่นแทน 1 พูด 3 จะเป็นเรื่องแปลกเพราะจะพิจารณาเฉพาะองค์ประกอบที่สามถัดไปในทั้งสองทิศทางเท่านั้น แต่ไม่ใช่ neihgbors โดยตรง
Sven Marnach

1
@Sven Marnach: สูตรที่คุณเชื่อมโยงทำให้สัญญาณล่าช้า มีสูตรที่สองซึ่งใช้filtfiltจาก scipy.signal
bobrobbob

2
เพียงเพื่อประโยชน์ของมันการแทนที่<ด้วย>จะให้ maxima ในท้องถิ่นแทน minima
DarkCygnus

1
@SvenMarnach ฉันใช้วิธีแก้ปัญหาข้างต้นของคุณเพื่อแก้ปัญหาของฉันที่โพสต์ไว้ที่นี่stackoverflow.com/questions/57403659/…แต่ฉันได้ผลลัพธ์[False False]อะไรจะเป็นปัญหาที่นี่?
Msquare

221

ใน SciPy> = 0.11

import numpy as np
from scipy.signal import argrelextrema

x = np.random.random(12)

# for local maxima
argrelextrema(x, np.greater)

# for local minima
argrelextrema(x, np.less)

ผลิต

>>> x
array([ 0.56660112,  0.76309473,  0.69597908,  0.38260156,  0.24346445,
    0.56021785,  0.24109326,  0.41884061,  0.35461957,  0.54398472,
    0.59572658,  0.92377974])
>>> argrelextrema(x, np.greater)
(array([1, 5, 7]),)
>>> argrelextrema(x, np.less)
(array([4, 6, 8]),)

หมายเหตุนี่คือดัชนีของ x ที่เป็นค่าสูงสุด / นาทีในพื้นที่ ในการรับค่าลอง:

>>> x[argrelextrema(x, np.greater)[0]]

scipy.signalยังให้argrelmaxและargrelminสำหรับการค้นหา maxima และ minima ตามลำดับ


1
ความหมายของ 12 คืออะไร?
marshmallow

7
@marshmallow: np.random.random(12)สร้าง 12 argrelextremaค่าสุ่มพวกเขาจะถูกนำมาใช้เพื่อแสดงให้เห็นถึงฟังก์ชั่น
sebix

2
หากอินพุตเป็นtest02=np.array([10,4,4,4,5,6,7,6])ก็จะไม่ทำงาน ไม่รับรู้ค่าต่อเนื่องเป็น minima ในเครื่อง
Leos313

1
ขอบคุณ @Cleb ฉันต้องการชี้ให้เห็นปัญหาอื่น ๆ : แล้วจุดสูงสุดของอาร์เรย์ล่ะ? องค์ประกอบแรกเป็นค่าสูงสุดในท้องถิ่นเช่นกันเนื่องจากองค์ประกอบสุดท้ายของอาร์เรย์เป็นค่าต่ำสุดในเครื่องด้วย และยังไม่ส่งคืนจำนวนค่าที่สร้างต่อเนื่องกัน แต่ผมเสนอวิธีการแก้ปัญหาในรหัสของคำถามนี้ได้ที่นี่ ขอบคุณ!!
Leos313

1
ขอบคุณนี่เป็นหนึ่งในวิธีแก้ปัญหาที่ดีที่สุดที่ฉันพบ
Noufal E

37

สำหรับเส้นโค้งที่ไม่มีเสียงรบกวนมากเกินไปขอแนะนำให้ใช้ข้อมูลโค้ดขนาดเล็กต่อไปนี้:

from numpy import *

# example data with some peaks:
x = linspace(0,4,1e3)
data = .2*sin(10*x)+ exp(-abs(2-x)**2)

# that's the line, you need:
a = diff(sign(diff(data))).nonzero()[0] + 1 # local min+max
b = (diff(sign(diff(data))) > 0).nonzero()[0] + 1 # local min
c = (diff(sign(diff(data))) < 0).nonzero()[0] + 1 # local max


# graphical output...
from pylab import *
plot(x,data)
plot(x[b], data[b], "o", label="min")
plot(x[c], data[c], "o", label="max")
legend()
show()

+1เป็นสิ่งสำคัญเพราะdiffจะช่วยลดจำนวนดัชนีเดิม


1
การใช้งานฟังก์ชัน numpy ที่ซ้อนกันได้ดี! แต่โปรดทราบว่าสิ่งนี้จะพลาด maxima ที่ปลายทั้งสองข้างของอาร์เรย์ :)
danodonovan

2
สิ่งนี้จะดูแปลก ๆ หากมีค่าซ้ำ ๆ เช่นถ้าคุณใช้อาร์เรย์[1, 2, 2, 3, 3, 3, 2, 2, 1]แม็กซิม่าในพื้นที่จะอยู่ระหว่าง 3 ที่อยู่ตรงกลางอย่างชัดเจน แต่ถ้าคุณเรียกใช้ฟังก์ชันที่คุณให้ไว้คุณจะได้รับ maximas ที่ดัชนี 2,6 และ minimas ที่ดัชนี 1,3,5,7 ซึ่งสำหรับฉันแล้วไม่สมเหตุสมผลเท่าไหร่
Korem

5
เพื่อหลีกเลี่ยงนี้+1แทนการใช้งานnp.diff() np.gradient()
ankostis

ฉันรู้ว่าเธรดนี้มีอายุหลายปีแล้ว แต่ก็คุ้มที่จะเพิ่มว่าหากเส้นโค้งของคุณมีเสียงดังเกินไปคุณสามารถลองใช้การกรองความถี่ต่ำก่อนเพื่อให้ราบรื่น อย่างน้อยที่สุดสำหรับฉันการใช้สูงสุด / นาทีในพื้นที่ส่วนใหญ่ของฉันใช้สำหรับค่าสูงสุด / นาทีทั่วโลกภายในบางพื้นที่ (e, g, ยอดเขาใหญ่และหุบเขาไม่ใช่ทุกรูปแบบในข้อมูล)
marcman

25

อีกแนวทางหนึ่ง (คำมากขึ้นรหัสน้อยลง) ที่อาจช่วยได้:

ตำแหน่งที่ตั้งของ maxima และ minima ในพื้นที่ยังเป็นตำแหน่งของจุดตัดศูนย์ของอนุพันธ์แรก โดยทั่วไปแล้วการหาจุดตัดเป็นศูนย์จะง่ายกว่าการหา maxima และ minima ในพื้นที่โดยตรง

น่าเสียดายที่อนุพันธ์แรกมีแนวโน้มที่จะ "ขยาย" สัญญาณรบกวนดังนั้นเมื่อมีสัญญาณรบกวนที่สำคัญอยู่ในข้อมูลต้นฉบับอนุพันธ์อันดับแรกจะใช้ได้ดีที่สุดหลังจากที่ข้อมูลต้นฉบับมีการปรับให้เรียบในระดับหนึ่งแล้วเท่านั้น

เนื่องจากในความหมายที่ง่ายที่สุดคือตัวกรองความถี่ต่ำการปรับให้เรียบมักจะทำได้ดีที่สุด (ดีและง่ายที่สุด) โดยใช้เคอร์เนล Convolution และ "การสร้าง" ที่เคอร์เนลสามารถให้ความสามารถในการรักษา / เพิ่มคุณสมบัติได้อย่างน่าประหลาดใจ . กระบวนการค้นหาเคอร์เนลที่เหมาะสมสามารถทำได้โดยอัตโนมัติโดยใช้หลายวิธี แต่วิธีที่ดีที่สุดอาจเป็นแรงเดรัจฉานอย่างง่าย (เร็วมากสำหรับการค้นหาเมล็ดขนาดเล็ก) เคอร์เนลที่ดีจะ (ตามที่ตั้งใจไว้) บิดเบือนข้อมูลต้นฉบับอย่างมาก แต่จะไม่ส่งผลกระทบต่อตำแหน่งของยอดเขา / หุบเขาที่น่าสนใจ

โชคดีที่บ่อยครั้งที่เคอร์เนลที่เหมาะสมสามารถสร้างได้ผ่าน SWAG ง่ายๆ ("การเดาที่มีการศึกษา") ความกว้างของเคอร์เนลที่ปรับให้เรียบควรกว้างกว่าจุดสูงสุดที่ "น่าสนใจ" ที่กว้างที่สุดที่คาดไว้ในข้อมูลต้นฉบับเล็กน้อยและรูปร่างของมันจะคล้ายกับจุดสูงสุดนั้น (เวฟเล็ตที่ปรับขนาดเดียว) สำหรับเมล็ดที่เก็บค่าเฉลี่ย (ตัวกรองการปรับความเรียบที่ดีควรเป็นอย่างไร) ผลรวมขององค์ประกอบเคอร์เนลควรเท่ากับ 1.00 อย่างแม่นยำและเคอร์เนลควรสมมาตรเกี่ยวกับจุดศูนย์กลาง (หมายความว่าจะมีองค์ประกอบจำนวนคี่

ด้วยเคอร์เนลที่ปรับให้เรียบที่เหมาะสมที่สุด (หรือเมล็ดจำนวนเล็กน้อยที่ปรับให้เหมาะสมกับเนื้อหาข้อมูลที่แตกต่างกัน) ระดับของการทำให้เรียบจะกลายเป็นปัจจัยในการปรับขนาดสำหรับ ("กำไร" ของ) เคอร์เนล Convolution

การกำหนดระดับการทำให้เรียบ "ที่ถูกต้อง (เหมาะสมที่สุด) (อัตราขยายของเคอร์เนลคอนโวลูชั่น) สามารถทำได้โดยอัตโนมัติ: เปรียบเทียบค่าเบี่ยงเบนมาตรฐานของข้อมูลอนุพันธ์แรกกับค่าเบี่ยงเบนมาตรฐานของข้อมูลที่ปรับให้เรียบ วิธีที่อัตราส่วนของค่าเบี่ยงเบนมาตรฐานทั้งสองเปลี่ยนแปลงไปตามการเปลี่ยนแปลงของระดับของลูกเบี้ยวที่ปรับให้เรียบใช้เพื่อทำนายค่าการปรับให้เรียบที่มีประสิทธิภาพ การรันข้อมูลด้วยตนเองเพียงไม่กี่รายการ (ซึ่งเป็นตัวแทนอย่างแท้จริง) ควรเป็นสิ่งที่จำเป็น

วิธีแก้ปัญหาก่อนหน้านี้ทั้งหมดที่โพสต์ไว้ข้างต้นจะคำนวณอนุพันธ์แรก แต่ไม่ถือว่าเป็นการวัดทางสถิติและไม่ได้ใช้วิธีแก้ปัญหาข้างต้นที่พยายามดำเนินการตามคุณสมบัติในการรักษา / เพิ่มประสิทธิภาพการปรับให้เรียบ (เพื่อช่วยให้เสียงดัง "กระโดดอยู่เหนือ")

ในที่สุดข่าวร้าย: การค้นหาจุดสูงสุดที่ "จริง" กลายเป็นความเจ็บปวดเมื่อสัญญาณรบกวนยังมีคุณลักษณะที่ดูเหมือนยอดจริง (แบนด์วิดท์ที่ทับซ้อนกัน) วิธีแก้ปัญหาที่ซับซ้อนมากขึ้นต่อไปโดยทั่วไปคือการใช้คอนโวลูชั่นเคอร์เนลที่ยาวขึ้น ("รูรับแสงเคอร์เนลที่กว้างขึ้น") ซึ่งคำนึงถึงความสัมพันธ์ระหว่างยอด "จริง" ที่อยู่ติดกัน (เช่นอัตราต่ำสุดหรือสูงสุดสำหรับการเกิดสูงสุด) หรือใช้หลาย ๆ Convolution ส่งผ่านโดยใช้เมล็ดที่มีความกว้างต่างกัน (แต่ถ้าเร็วกว่าเท่านั้น: มันเป็นความจริงพื้นฐานทางคณิตศาสตร์ที่การ Convolution เชิงเส้นที่ดำเนินการตามลำดับสามารถถูกแปลงรวมกันเป็น Convolution เดียวได้เสมอ) แต่มักจะง่ายกว่ามากในการค้นหาลำดับของเมล็ดที่มีประโยชน์ (ที่มีความกว้างต่างกัน) และนำมาประกอบเข้าด้วยกันมากกว่าที่จะค้นหาเคอร์เนลสุดท้ายโดยตรงในขั้นตอนเดียว

หวังว่านี่จะให้ข้อมูลเพียงพอที่จะให้ Google (และอาจเป็นข้อความสถิติที่ดี) เติมเต็มช่องว่าง ฉันหวังว่าฉันจะมีเวลาให้ตัวอย่างที่ใช้งานได้จริงหรือลิงก์ไปยังตัวอย่าง ถ้าใครเจอออนไลน์ก็โพสได้เลย!


25

ในฐานะของ SciPy รุ่น 1.1 คุณยังสามารถใช้find_peaks ด้านล่างนี้เป็นสองตัวอย่างที่นำมาจากเอกสารประกอบเอง

การใช้heightอาร์กิวเมนต์เราสามารถเลือก maxima ทั้งหมดที่อยู่เหนือเกณฑ์ที่กำหนดได้ (ในตัวอย่างนี้คือ maxima ที่ไม่ใช่ค่าลบทั้งหมดสิ่งนี้จะมีประโยชน์มากหากต้องจัดการกับพื้นฐานที่มีเสียงดังหากคุณต้องการค้นหา minima ให้คูณที่คุณป้อน โดย-1):

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

x = electrocardiogram()[2000:4000]
peaks, _ = find_peaks(x, height=0)
plt.plot(x)
plt.plot(peaks, x[peaks], "x")
plt.plot(np.zeros_like(x), "--", color="gray")
plt.show()

ใส่คำอธิบายภาพที่นี่

ข้อโต้แย้งที่เป็นประโยชน์อย่างยิ่งอีกประการหนึ่งคือdistanceกำหนดระยะห่างต่ำสุดระหว่างสองยอด:

peaks, _ = find_peaks(x, distance=150)
# difference between peaks is >= 150
print(np.diff(peaks))
# prints [186 180 177 171 177 169 167 164 158 162 172]

plt.plot(x)
plt.plot(peaks, x[peaks], "x")
plt.show()

ใส่คำอธิบายภาพที่นี่


10

ทำไมไม่ใช้ Scipy ฟังก์ชันในตัวsignal.find_peaks_cwtในการทำงาน

from scipy import signal
import numpy as np

#generate junk data (numpy 1D arr)
xs = np.arange(0, np.pi, 0.05)
data = np.sin(xs)

# maxima : use builtin function to find (max) peaks
max_peakind = signal.find_peaks_cwt(data, np.arange(1,10))

# inverse  (in order to find minima)
inv_data = 1/data
# minima : use builtin function fo find (min) peaks (use inversed data)
min_peakind = signal.find_peaks_cwt(inv_data, np.arange(1,10))

#show results
print "maxima",  data[max_peakind]
print "minima",  data[min_peakind]

ผล:

maxima [ 0.9995736]
minima [ 0.09146464]

ความนับถือ


7
แทนที่จะทำการหาร (ด้วยการสูญเสียความแม่นยำที่เป็นไปได้) ทำไมไม่คูณด้วย -1 เพื่อเปลี่ยนจาก maxima เป็น minima
Livius

ฉันพยายามเปลี่ยน '1 / data' เป็น 'data * -1' แต่เกิดข้อผิดพลาดคุณช่วยแชร์วิธีใช้วิธีการของคุณได้ไหม
A STEFANI

อาจเป็นเพราะเราไม่ต้องการกำหนดให้ผู้ใช้ปลายทางติดตั้ง scipy เพิ่มเติม
Damian Yerrick

5

ปรับปรุง:numpy.diffฉันไม่ได้มีความสุขกับการไล่ระดับสีเพื่อให้ผมพบว่ามันมีความน่าเชื่อถือมากขึ้นในการใช้งาน โปรดแจ้งให้เราทราบหากเป็นไปตามที่คุณต้องการ

เกี่ยวกับปัญหาของเสียงรบกวนปัญหาทางคณิตศาสตร์คือการค้นหา maxima / minima หากเราต้องการดูสัญญาณรบกวนเราสามารถใช้บางอย่างเช่น convolve ซึ่งได้กล่าวไว้ก่อนหน้านี้

import numpy as np
from matplotlib import pyplot

a=np.array([10.3,2,0.9,4,5,6,7,34,2,5,25,3,-26,-20,-29],dtype=np.float)

gradients=np.diff(a)
print gradients


maxima_num=0
minima_num=0
max_locations=[]
min_locations=[]
count=0
for i in gradients[:-1]:
        count+=1

    if ((cmp(i,0)>0) & (cmp(gradients[count],0)<0) & (i != gradients[count])):
        maxima_num+=1
        max_locations.append(count)     

    if ((cmp(i,0)<0) & (cmp(gradients[count],0)>0) & (i != gradients[count])):
        minima_num+=1
        min_locations.append(count)


turning_points = {'maxima_number':maxima_num,'minima_number':minima_num,'maxima_locations':max_locations,'minima_locations':min_locations}  

print turning_points

pyplot.plot(a)
pyplot.show()

คุณรู้หรือไม่ว่าการไล่ระดับสีนี้คำนวณอย่างไร? หากคุณมีข้อมูลที่มีเสียงดังอาจทำให้การไล่ระดับสีเปลี่ยนไปมาก แต่นั่นไม่จำเป็นต้องหมายความว่ามีสูงสุด / นาที
Navi

ใช่ฉันรู้อย่างไรก็ตามข้อมูลที่มีเสียงดังเป็นปัญหาอื่น สำหรับสิ่งนั้นฉันเดาว่าใช้ Convolve
Mike Vella

ฉันต้องการบางสิ่งที่คล้ายกันสำหรับโปรเจ็กต์ที่ฉันกำลังทำอยู่และใช้เมธอด numpy.diff ที่กล่าวถึงข้างต้นฉันคิดว่ามันอาจเป็นประโยชน์ที่จะพูดถึงว่าสำหรับข้อมูลของฉันรหัสข้างต้นพลาด maxima และ minima ไปเล็กน้อยโดยการเปลี่ยนคำกลางทั้งสอง ถ้าข้อความเป็น <= และ> = ตามลำดับฉันสามารถจับจุดทั้งหมดได้

5

ในขณะที่คำถามนี้เก่าจริงๆ ฉันเชื่อว่ามีวิธีการที่ง่ายกว่ามากใน numpy (ซับเดียว)

import numpy as np

list = [1,3,9,5,2,5,6,9,7]

np.diff(np.sign(np.diff(list))) #the one liner

#output
array([ 0, -2,  0,  2,  0,  0, -2])

ในการหาค่าสูงสุดหรือต่ำสุดในพื้นที่เราต้องการค้นหาเมื่อความแตกต่างระหว่างค่าในรายการ (3-1, 9-3 ... ) เปลี่ยนจากบวกเป็นลบ (สูงสุด) หรือลบเป็นบวก (นาที) ดังนั้นก่อนอื่นเราพบความแตกต่าง จากนั้นเราจะพบเครื่องหมายแล้วเราจะพบการเปลี่ยนแปลงในเครื่องหมายโดยรับความแตกต่างอีกครั้ง (เรียงลำดับเหมือนอนุพันธ์อันดับหนึ่งและสองในแคลคูลัสมีเพียงเราเท่านั้นที่มีข้อมูลไม่ต่อเนื่องและไม่มีฟังก์ชันต่อเนื่อง)

ผลลัพธ์ในตัวอย่างของฉันไม่มี extrema (ค่าแรกและค่าสุดท้ายในรายการ) เช่นเดียวกับแคลคูลัสถ้าอนุพันธ์อันดับสองเป็นลบคุณจะมี max และถ้ามันเป็นบวกคุณจะมี min

ดังนั้นเราจึงมีการจับคู่ดังต่อไปนี้:

[1,  3,  9,  5,  2,  5,  6,  9,  7]
    [0, -2,  0,  2,  0,  0, -2]
        Max     Min         Max

1
ฉันคิดว่าคำตอบ (ดี!) นี้เหมือนกับคำตอบของ RC จากปี 2012 หรือไม่? เขาเสนอวิธีแก้ปัญหาแบบบรรทัดเดียวสามวิธีขึ้นอยู่กับว่าผู้โทรต้องการ mins, maxes หรือทั้งสองอย่างถ้าฉันอ่านวิธีแก้ปัญหาของเขาอย่างถูกต้อง
Brandon Rhodes

3

วิธีแก้ปัญหาเหล่านี้ไม่ได้ผลสำหรับฉันเนื่องจากฉันต้องการหาจุดสูงสุดที่อยู่ตรงกลางของค่าที่เกิดซ้ำเช่นกัน ตัวอย่างเช่นใน

ar = np.array([0,1,2,2,2,1,3,3,3,2,5,0])

คำตอบควรเป็น

array([ 3,  7, 10], dtype=int64)

ฉันทำสิ่งนี้โดยใช้ลูป ฉันรู้ว่ามันไม่สะอาดสุด ๆ แต่ก็ทำให้งานเสร็จ

def findLocalMaxima(ar):
# find local maxima of array, including centers of repeating elements    
maxInd = np.zeros_like(ar)
peakVar = -np.inf
i = -1
while i < len(ar)-1:
#for i in range(len(ar)):
    i += 1
    if peakVar < ar[i]:
        peakVar = ar[i]
        for j in range(i,len(ar)):
            if peakVar < ar[j]:
                break
            elif peakVar == ar[j]:
                continue
            elif peakVar > ar[j]:
                peakInd = i + np.floor(abs(i-j)/2)
                maxInd[peakInd.astype(int)] = 1
                i = j
                break
    peakVar = ar[i]
maxInd = np.where(maxInd)[0]
return maxInd 

1
import numpy as np
x=np.array([6,3,5,2,1,4,9,7,8])
y=np.array([2,1,3,5,3,9,8,10,7])
sortId=np.argsort(x)
x=x[sortId]
y=y[sortId]
minm = np.array([])
maxm = np.array([])
i = 0
while i < length-1:
    if i < length - 1:
        while i < length-1 and y[i+1] >= y[i]:
            i+=1

        if i != 0 and i < length-1:
            maxm = np.append(maxm,i)

        i+=1

    if i < length - 1:
        while i < length-1 and y[i+1] <= y[i]:
            i+=1

        if i < length-1:
            minm = np.append(minm,i)
        i+=1


print minm
print maxm

minmและmaxmมีดัชนีของ minima และ maxima ตามลำดับ สำหรับชุดข้อมูลขนาดใหญ่จะให้ maximas / minimas จำนวนมากดังนั้นในกรณีนี้จึงทำให้เส้นโค้งเรียบก่อนแล้วจึงใช้อัลกอริทึมนี้


มันดูน่าสนใจ ไม่มีห้องสมุด มันทำงานอย่างไร?
john ktejik

1
สำรวจเส้นโค้งจากจุดเริ่มต้นและดูว่าคุณกำลังขึ้นหรือลงอย่างต่อเนื่องเมื่อคุณเปลี่ยนจากขึ้นเป็นลงหมายความว่าคุณมี maxima ถ้าคุณกำลังลงไปข้างบนคุณจะมี minima
prtkp

1

อีกวิธีหนึ่งโดยใช้ตัวดำเนินการขยายเป็นหลัก:

import numpy as np
from scipy.ndimage import rank_filter

def find_local_maxima(x):
   x_dilate = rank_filter(x, -1, size=3)
   return x_dilate == x

และสำหรับ minima:

def find_local_minima(x):
   x_erode = rank_filter(x, -0, size=3)
   return x_erode == x

นอกจากนี้จากการscipy.ndimageที่คุณสามารถแทนที่rank_filter(x, -1, size=3)ด้วยgrey_dilationและมีrank_filter(x, 0, size=3) grey_erosionสิ่งนี้ไม่จำเป็นต้องมีการจัดเรียงในเครื่องดังนั้นจึงเร็วกว่าเล็กน้อย


มันทำงานได้อย่างถูกต้องสำหรับปัญหานี้ นี่คือทางออกที่สมบูรณ์แบบ (+1)
Leos313

0

อีกอันหนึ่ง:


def local_maxima_mask(vec):
    """
    Get a mask of all points in vec which are local maxima
    :param vec: A real-valued vector
    :return: A boolean mask of the same size where True elements correspond to maxima. 
    """
    mask = np.zeros(vec.shape, dtype=np.bool)
    greater_than_the_last = np.diff(vec)>0  # N-1
    mask[1:] = greater_than_the_last
    mask[:-1] &= ~greater_than_the_last
    return mask
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.