Можете ли вы предложить функцию модуля из numpy / scipy, которая может находить локальные максимумы / минимумы в массиве 1D numpy? Очевидно, самый простой подход - взглянуть на ближайших соседей, но я хотел бы иметь приемлемое решение, которое является частью дистрибутива numpy.
116
Ответы:
Если вы ищете все записи в массиве 1d,
a
меньшие, чем их соседи, вы можете попробоватьВы также можете сгладить свой массив перед этим шагом, используя
numpy.convolve()
.Я не думаю, что для этого есть специальная функция.
источник
<
с>
даст вам локальные максимумы вместо минимумов[False False]
чем может быть проблема?В SciPy> = 0.11
Производит
Обратите внимание, что это индексы x, которые являются локальными max / min. Чтобы получить значения, попробуйте:
scipy.signal
также обеспечиваетargrelmax
иargrelmin
для нахождения максимумов и минимумов соответственно.источник
np.random.random(12)
генерирует 12 случайных значений, они используются для демонстрации функцииargrelextrema
.test02=np.array([10,4,4,4,5,6,7,6])
, значит не работает. Он не распознает последовательные значения как локальные минимумы.Для кривых с небольшим шумом я рекомендую следующий небольшой фрагмент кода:
Это
+1
важно, потому чтоdiff
уменьшает исходный порядковый номер.источник
[1, 2, 2, 3, 3, 3, 2, 2, 1]
, очевидно, что локальные максимумы находятся где-то между тройками в середине. Но если вы запустите предоставленные вами функции, вы получите максимумы с индексами 2,6 и минимумы с индексами 1,3,5,7, что для меня не имеет большого смысла.+1
вместоnp.diff()
использованияnp.gradient()
.Другой подход (больше слов, меньше кода), который может помочь:
Положения локальных максимумов и минимумов также являются местоположениями пересечений нуля первой производной. Как правило, гораздо проще найти пересечение нуля, чем непосредственно локальные максимумы и минимумы.
К сожалению, первая производная имеет тенденцию «усиливать» шум, поэтому, когда в исходных данных присутствует значительный шум, первую производную лучше всего использовать только после применения некоторой степени сглаживания к исходным данным.
Поскольку сглаживание, в простейшем смысле, является фильтром нижних частот, сглаживание часто лучше (ну, проще всего) выполняется с использованием ядра свертки, и «формирование» этого ядра может обеспечить удивительное количество возможностей сохранения / улучшения функций. , Процесс поиска оптимального ядра можно автоматизировать с помощью различных средств, но лучшим может быть простой перебор (достаточно быстро для поиска небольших ядер). Хорошее ядро (как и предполагалось) сильно исказит исходные данные, но НЕ повлияет на расположение интересующих пиков / впадин.
К счастью, довольно часто подходящее ядро можно создать с помощью простого SWAG («обоснованное предположение»). Ширина сглаживающего ядра должна быть немного шире, чем самый широкий ожидаемый «интересный» пик в исходных данных, а его форма будет напоминать этот пик (одномасштабный вейвлет). Для ядер, сохраняющих среднее значение (каким должен быть любой хороший сглаживающий фильтр), сумма элементов ядра должна быть точно равна 1,00, и ядро должно быть симметричным относительно своего центра (то есть у него будет нечетное количество элементов.
При оптимальном сглаживающем ядре (или небольшом количестве ядер, оптимизированных для различного содержания данных) степень сглаживания становится масштабным коэффициентом («усилением») ядра свертки.
Определение «правильной» (оптимальной) степени сглаживания (усиления ядра свертки) можно даже автоматизировать: сравните стандартное отклонение данных первой производной со стандартным отклонением сглаженных данных. То, как соотношение двух стандартных отклонений изменяется с изменением степени сглаживания кулачка, можно использовать для прогнозирования эффективных значений сглаживания. Все, что нужно, - это несколько ручных прогонов данных (которые действительно репрезентативны).
Все предыдущие решения, опубликованные выше, вычисляют первую производную, но они не рассматривают ее как статистическую меру, а также вышеупомянутые решения не пытаются выполнить сглаживание с сохранением / улучшением характеристик (чтобы помочь тонким пикам "перепрыгнуть" над шумом).
Наконец, плохая новость: поиск «настоящих» пиков становится головной болью, когда шум также имеет характеристики, которые выглядят как настоящие пики (перекрывающаяся полоса пропускания). Следующим более сложным решением обычно является использование более длинного ядра свертки («более широкая апертура ядра»), которое учитывает взаимосвязь между соседними «реальными» пиками (например, минимальную или максимальную частоту появления пика) или использование нескольких свертка проходит с использованием ядер, имеющих разную ширину (но только если это быстрее: фундаментальная математическая истина заключается в том, что линейные свертки, выполняемые последовательно, всегда могут быть свернуты вместе в одну свертку). Но зачастую гораздо проще сначала найти последовательность полезных ядер (разной ширины) и свести их вместе, чем напрямую найти окончательное ядро за один шаг.
Надеюсь, это предоставит достаточно информации, чтобы позволить Google (и, возможно, хорошей статистике) заполнить пробелы. Мне очень жаль, что у меня не было времени предоставить рабочий пример или ссылку на него. Если кто-нибудь встретит что-нибудь в сети, опубликуйте его здесь!
источник
Начиная с версии 1.1 SciPy, вы также можете использовать find_peaks . Ниже приведены два примера, взятых из самой документации.
Используя
height
аргумент, можно выбрать все максимумы выше определенного порога (в этом примере все неотрицательные максимумы; это может быть очень полезно, если приходится иметь дело с зашумленной базовой линией; если вы хотите найти минимумы, просто умножьте введенные вами данные автор-1
):Еще один чрезвычайно полезный аргумент
distance
, который определяет минимальное расстояние между двумя пиками:источник
Почему бы не использовать встроенную функцию Scipy signal.find_peaks_cwt для выполнения этой работы?
полученные результаты:
С уважением
источник
Обновление: мне не нравился градиент, поэтому я нашел его более надежным в использовании
numpy.diff
. Пожалуйста, дайте мне знать, если он делает то, что вы хотите.Что касается шума, математическая проблема состоит в том, чтобы найти максимумы / минимумы, если мы хотим посмотреть на шум, мы можем использовать что-то вроде свертки, о которой упоминалось ранее.
источник
Пока этот вопрос действительно старый. Я считаю, что в numpy (однострочный) есть гораздо более простой подход.
Чтобы найти локальный максимум или минимум, мы, по сути, хотим найти, когда разница между значениями в списке (3-1, 9-3 ...) изменяется с положительного на отрицательное (max) или с отрицательного на положительное (min). Поэтому сначала находим разницу. Затем мы находим знак, а затем мы находим изменения знака, снова взяв разницу. (Это что-то вроде первой и второй производных в исчислении, только у нас есть дискретные данные и нет непрерывной функции.)
Результат в моем примере не содержит экстремумов (первое и последнее значения в списке). Кроме того, как и в исчислении, если вторая производная отрицательна, у вас есть max, а если она положительна, у вас есть min.
Таким образом, у нас получился следующий матч:
источник
Ни одно из этих решений не помогло мне, так как я также хотел найти пики в центре повторяющихся значений. например, в
ar = np.array([0,1,2,2,2,1,3,3,3,2,5,0])
ответ должен быть
Я сделал это с помощью петли. Я знаю, что он не очень чистый, но он выполняет свою работу.
источник
minm
иmaxm
содержат индексы минимумов и максимумов соответственно. Для огромного набора данных он даст много максимумов / минимумов, поэтому в этом случае сначала сгладьте кривую, а затем примените этот алгоритм.источник
Другое решение, использующее по существу оператор расширения:
а для минимумов:
Кроме того , от
scipy.ndimage
вас могут заменитьrank_filter(x, -1, size=3)
сgrey_dilation
иrank_filter(x, 0, size=3)
сgrey_erosion
. Это не требует локальной сортировки, поэтому выполняется немного быстрее.источник
Другой:
источник