Найти два локальных минимума в python

doctorwho спросил: 28 марта 2018 в 03:23 в: python

У меня есть список значений t. Мой код для поиска значений минимумов выглядит следующим образом:

for i in np.arange(0,499,1):
    if t[i]<t[i-1] and t[i]<t[i+1] :                       
        t_min.append(t[i])

Мои значения t меняются каждый раз, и, следовательно, может случиться, что один из минимумов происходит в начале или в конце в этом случае этот код не работает. Поэтому мне нужен общий код, который будет работать для любого диапазона значений t.

2 ответа

Есть решение
tanboon ответил: 29 марта 2018 в 04:12

Вы можете зациклить конец, используя оператор% и добавляя один к длине итератора. Это обрабатывает ваш массив "как круг", и это то, что вы действительно хотите.

t_min = []
for i in range(len(t)):
    if  t[i] < min(t[i - 1], t[(i + 1) % len(t)]):
        t_min.append(t[i])

Редактировать: Исправить диапазон значений, которые я беру, чтобы первый элемент не проверялся дважды Спасибо @Jasper за указание на это

Jasper ответил: 28 марта 2018 в 07:44
Это нормально, не могли бы вы объяснить это дальше? Также я думаю, что вы не должны использовать t[ i% len(t)] в условии, потому что таким образом вы дважды проверяете нулевой элемент, верно?
tanboon ответил: 29 марта 2018 в 04:16
Конечно! Для i = 1, ..., len (t) -1 вы проверяете элементы, которые не находятся ни на одном конце. Для i = 0 t [i-1] = t [-1] выбирает последний элемент массива, поэтому вы проверяете первый элемент. Для i = len (t) i% len (t) = 0, поэтому вы вернулись к циклу и получили первый элемент, одновременно проверяя последний. Вы правы, что мне не нужен len (t) +1, спасибо @Jasper
user6655984 ответил: 28 марта 2018 в 05:49

Вместо циклического перемещения по массиву я предлагаю использовать scipy.signal.argrelmin, который находит все локальные минимумы. Вы можете выбрать два из них, которые вам нравятся больше всего.

from scipy.signal import argrelmin
import numpy as np
t = np.sin(np.linspace(0, 4*np.pi, 500))
relmin = argrelmin(t)[0]
print(relmin)

В результате вы получите [187 437].

Чтобы обработать массив как обтекание, используйте argrelmin(t, mode=‘wrap’)


Без циклического преобразования argrelmin не распознает начало и конец массива как кандидатов на локальный минимум. (Существуют различные интерпретации "локального минимума": одна разрешает конечные точки, другая - нет.) Если вы хотите, чтобы конечные точки были включены, когда функция достигает минимума, сделайте это следующим образом:

if t[0] < t[1]:
    relmin = np.append(relmin, 0)
if t[-1] < t[-2]:
    relmin = np.append(relmin, len(t)-1)

Теперь выводим [187 437 0].