将列表中的值与上一个和下一个值进行比较

时间:2018-12-05 15:07:40

标签: python-3.x

我正在尝试编写一组简单的指令以返回一组数据中峰的索引。在我的实际数据集中,我有多个峰值(因此仅查找最大值或最小值是不够的)。出于我的目的,我可以将峰值定义为小于in中的值,也小于in中的后一个值(我正在寻找负峰)。

我有一个可行的示例,但是如果列表中有两个相同的数字,它将失败。

mylist = [10, 8, 5, 3, 1, 3, 4]
min =[]
for i in mylist[1:-1]: # the pre and post comparison means I have to start from item 2 to second last item
    pre = mylist.index(i)-1
    post = mylist.index(i)+1
    print('current i', i)
    print('index', pre, post)
    print('values pre post', mylist[pre], mylist[post])
    if i < mylist[pre] and i< mylist[post]:
       print('true')
       min.append(mylist.index(i))
    print('min=', min)

这似乎一直有效,直到到达列表中的第二个“ 3”(在位置5),在这种情况下,它会根据第一个“ 3”的任一侧的值对其求值。

....
current i 1
index 3 5
values pre post 3 3
true
current i 3
index 2 4
values pre post 5 1
min= [4]

如您所见,它正确地发现'1'之后的值是'3',但我认为它基本上是说索引5处的值= 3,所以值是3的任意一边,然后读取第3个。我的头这似乎是微不足道的,但被弄糊涂了。我的搜索以及在撰写本文时提出的建议问题都没有标记任何重复项,但是如果我是这件事的第一人,我会感到惊讶...

(也用于解释,我使用的是scipy find_peaks,但不适用于我的目的。如果最终数据点上升,它将最后一个数据点识别为峰值。例如[... 11, 12, 13, 14, 15],它将识别“ 15'(可能不是)。

2 个答案:

答案 0 :(得分:3)

当我尝试遍历mylist[1:-1]

时,我遇到了同样的问题

由于在第一个迭代中需要前一个元素的索引,而在最后一个迭代中需要后继元素,因此代码将丢失定位某些值的错误,并且还会出现'IndexError: list index out of range错误。 另外,您正在编写大量代码以将每次迭代的索引和值相关联,这些代码是内置在enumerate(list)函数中的

以下代码可以正常运行,并且可以满足您的需求:

mylist = [10, 8, 5, 3, 1, 3, 4]
peak = []     # min is a python keyword, so it is advised that you don't define it as a variable, we'll use peak to list all min values

# While iterating through indices and values, use enumerate
for i,x in enumerate(mylist):       # iterate through all indices
    if i == 0 or i == (len(mylist)-1):  # pass the first and last index
        pass
    else:
        pre = mylist[i-1]               # use the index variable i to locate pre 
        post = mylist [i+1]             # and post
        print ("Selected list >> Pre: {}, Index: {}, Post: {}".format(pre,x,post)) # updated the print line to make it more readable
        if pre > x < post:              # check if current element is between pre and post
            print ("True")
            peak.append(x)              # append to peak list if true
print (peak)

[Out]: 
Selected list >> Pre: 10, Index: 8, Post: 5
Selected list >> Pre: 8, Index: 5, Post: 3
Selected list >> Pre: 5, Index: 3, Post: 1
Selected list >> Pre: 3, Index: 1, Post: 3    # Peak found
True                                          # Print true
Selected list >> Pre: 1, Index: 3, Post: 4
[1]                                           # only 1 peak in the list

让我知道您是否对代码感到满意。

答案 1 :(得分:0)

如果您愿意使用numpy和scipy,则可以在numpy数组上使用scipy.argrelextrema来获取局部最小值(在https://stackoverflow.com/a/13491866/3651127之后):

import numpy as np
from scipy.signal import argrelextrema

mylist = [10, 8, 5, 3, 1, 3, 4]
x = np.array(mylist)

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

返回:

(array([4], dtype=int64),)