Обнаружение пиков в списке чисел и запись их позиций - PullRequest
0 голосов
/ 24 декабря 2018

Я пытаюсь создать некоторый код, который возвращает позиции и значения «пиков» (или локальных максимумов) числового массива.

Например, список arr = [0, 1, 2, 5, 1, 0] имеет пик вposition 3 со значением 5 (поскольку arr[3] равно 5).

Первый и последний элементы массива не будут рассматриваться как пики (в контексте математической функции, вы не знаете, что после и до, и, следовательно, вы не знаете, является ли это пиком или нет).

def pick_peaks(arr):
    print(arr)
    posPeaks = {
        "pos": [],
        "peaks": [],
    }
    startFound = False
    n = 0
    while startFound == False:
        if arr[n] == arr[n+1]:
            n += 1
        else:
            startFound = True

    endFound = False
    m = len(arr) - 1
    while endFound == False:
        if arr[m] == arr[m-1]:
            m -= 1
        else:
            endFound = True

    for i in range(n+1, m):
        if arr[i] == arr[i-1]:
            None
        elif arr[i] >= arr[i-1] and arr[i] >= arr[i+1]:
            posPeaks["pos"].append(i)
            posPeaks["peaks"].append(arr[i])

    return posPeaks

Моя проблема с плато.[1, 2, 2, 2, 1] имеет пик, а [1, 2, 2, 2, 3] - нет.Когда плато является пиком, записывается первая позиция плато.

Любая помощь приветствуется.

Ответы [ 4 ]

0 голосов
/ 24 декабря 2018

Более короткий скрипт может быть:

data_array = [1, 2, 5, 4, 6, 9]
# Delete the first and the last element of the data array. 
reduced_array = [ data_array[i] for i in range(1, len(data_array)-1) ]
# Find the maximum value of the modified array 
peak_value = max(reduced_array)
# Print out the maximum value and its index in the data array. 
print 'The peak value is: ' + str(peak_value)
print 'And its position is: ' + str(data_array.index(peak_value))

Вывод:

The peak value is: 6
And its position is: 4
0 голосов
/ 24 декабря 2018

Я предлагаю вам использовать groupby для группировки смежных равных значений, затем для каждой группы сохранить первую позицию, например для [1, 2, 2, 2, 1], создаст следующий список, следующий список кортежей [(1, 0), (2, 1), (1, 4)], собрав все вместе:

from itertools import groupby


def peaks(data):
    start = 0
    sequence = []
    for key, group in groupby(data):
        sequence.append((key, start))
        start += sum(1 for _ in group)

    for (b, bi), (m, mi), (a, ai) in zip(sequence, sequence[1:], sequence[2:]):
        if b < m and a < m:
            yield m, mi


print(list(peaks([0, 1, 2, 5, 1, 0])))
print(list(peaks([1, 2, 2, 2, 1])))
print(list(peaks([1, 2, 2, 2, 3])))

Выход

[(5, 3)]
[(2, 1)]
[]
0 голосов
/ 24 декабря 2018

Вот довольно простая функция генератора.Просто зациклите и сохраните необходимое состояние: i (последний индекс «роста»), up (истина, если последнее изменение значения было «ростом»)

def peaks(ar):
    i, up = 0, False
    for j in range(1, len(ar)):
        prev, val = ar[j-1], ar[j]
        if up and val < prev:
            yield prev, i
            up = False
        if val > prev:
            i, up = j, True

>>> list(peaks([0,1,2,5,1,0]))
[(5, 3)]
>>> list(peaks([0,1,2,5,1,2,0]))
[(5, 3), (2, 5)]
>>> list(peaks([0,1,2,5,1,2,0,3]))
[(5, 3), (2, 5)]
>>> list(peaks([1,2,2,2,1]))
[(2, 1)]
>>> list(peaks([1,2,2,2,3]))
[]
0 голосов
/ 24 декабря 2018

Вы можете использовать тот же алгоритм с плато, если вы можете предварительно обработать данные, чтобы удалить повторяющиеся числа и сохранить только 1 уникальный номер.Таким образом, вы можете преобразовать пример [1, 2, 2, 2, 1] в [1, 2, 1] и применить тот же алгоритм.

Редактировать: Код:

from itertools import groupby

def process_data(data):
    return [list(val for num in group) for val, group in groupby(data)]


def peaks(arr):
    #print(arr)
    posPeaks = {
    "pos": [],
    "peaks": [],
    }
    startFound = False
    n = 0
    while startFound == False:
        if arr[n][0] == arr[n+1][0]:
            n += 1
        else:
            startFound = True

    endFound = False
    m = len(arr) - 1
    while endFound == False:
        if arr[m][0] == arr[m-1][0]:
            m -= 1
        else:
            endFound = True

    for i in range(n+1, m):
        if arr[i][0] == arr[i-1][0]:
            None
        elif arr[i][0] >= arr[i-1][0] and arr[i][0] >= arr[i+1][0]:
            pos = sum([len(arr[idx]) for idx in range(i)])
            posPeaks["pos"].append(pos) #.append(i)
            posPeaks["peaks"].append(arr[i][0])
    return posPeaks



print(peaks(process_data([0, 1, 2, 5, 1, 0])))
print(peaks(process_data([1, 2, 2, 2, 1])))
print(peaks(process_data([1, 2, 2, 2, 3])))

Вывод:

{'pos': [3], 'peaks': [5]}
{'pos': [1], 'peaks': [2]}
{'pos': [], 'peaks': []}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...