Как определить восходящий и нисходящий тренд в списке?

Много списка Python с некоторыми данными, как обнаружить данные в списке, встречаются вниз, а затем вверх. Например:

a1 = [8,6,4,1,-2,-6,5,8,9,87] 
a2 = [8,6,4,1,-2,-6,5,-8,9,10]

где данные в a1 идут вниз, а затем вверх, ожидайте печати «ОК» но данные в a2 идут вниз, затем вверх, затем вниз, в последнюю очередь вверх, ожидайте печати 'NG' как это сделать на питоне?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
62
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете перебирать список по три элемента за раз и подсчитывать типы пиков, которые вы видите, либо вниз, либо вверх. В конце верните True, если есть только одна нисходящая вершина, False иначе.

def one_downward_peak(data):
    upward_peaks = 0
    downward_peaks = 0

    for i in range(len(data) - 2):
        a, b, c = data[i:i+3]
        if a > b < c:
            downward_peaks += 1
        elif a < b > c:
            upward_peaks += 1

    return upward_peaks == 0 and downward_peaks == 1
>>> one_downward_peak([8,6,4,1,-2,-6,5,8,9,87])
True
>>> one_downward_peak([8,6,4,1,-2,-6,5,-8,9,10])
False

Если вы хотите оптимизировать это, вы можете выйти раньше, как только увидите восходящий пик.

Одним из простых способов исправить ваш код было бы использовать itertools.groupby для удаления плоских линий: data = [k for k,_ in itertools.groupby(data)] в начале вашей функции.

mozway 18.02.2023 10:15
Ответ принят как подходящий

Вы можете вычислить знак последовательных различий, а затем сохранить только разные. Если это дает [-1, 1], это OK, иначе NG:

import numpy as np

def check(lst):
    # sign of successive difference
    s = np.sign(np.diff(lst))
    # mask to deduplicate successive values
    m1 = np.r_[True, s[:-1]!=s[1:]]
    # mask to remove flat lines
    m2 = s != 0
    # OK if both masks are True else NG
    return 'OK' if s[m1&m2].tolist() == [-1, 1] else 'NG'

check(a1)
# 'OK'

check(a2)
# 'NG'

check([2,1,1,2])
# 'OK'

Промежуточные продукты:

### first example

lst
# [8, 6, 4, 1, -2, -6, 5, 8, 9, 87]

s = np.sign(np.diff(lst))
# array([-1, -1, -1, -1, -1,  1,  1,  1,  1])

s[np.r_[True, s[:-1]!=s[1:]]].tolist()
# [-1, 1]

### second example

lst
# [8, 6, 4, 1, -2, -6, 5, -8, 9, 10]

s = np.sign(np.diff(lst))
# array([-1, -1, -1, -1, -1,  1, -1,  1,  1])

s[np.r_[True, s[:-1]!=s[1:]]].tolist()
# [-1, 1, -1, 1]

Только что понял, что оба наших ответа не проходят проверку, когда пик плоский: .e.g. [2,1,1,2]

flakes 18.02.2023 09:57

@flakes спасибо! Хорошо подмечено, с этим легко справиться, удалив 0s, см. Обновление :)

mozway 18.02.2023 10:09

Другие вопросы по теме