find local maxima and their indices in a python list

Question:

I have a large data set and I am trying to find the local maxima and their indices. I have made it to get the local maxima but can’t find a way to get their indices.
The thing is that I need the maxima only for positive values and we should ignore the negative values. In other words, it would be like splitting the list in several segments with positive values and getting those maxima.

For example, the list can be smth like this:
test_data = [2, 35, -45, 56, 5, 67, 21, 320, 55, -140, -45, -98, -23, -23, 35, 67, 34, -30, -86, 4, -93, 35, 88, 32, 98, -6]

My code is:
`

def global_peaks(test_data):
    counter1 = []
    index = []
    global_peak = []
    global_idx = []
    for idx, data in enumerate(test_data):
        if data > 0:
            counter1.append(data)
            index.append(idx)                                    
        else:
            if(len(counter1) != 0):
                global_peak.append(max(counter1))
                index.append(idx)
                global_idx.append(index)
            counter1.clear()
            index.clear()
    return global_peak, global_idx
```
global_peaks(test_data)

```
([35, 320, 67, 4, 98], [[], [], [], [], []])
```
result are correct when it comes to the values, but not the indices
Asked By: ujku80

||

Answers:

def global_peaks(test_data):
    counter1 = []
    index = []
    global_peak = []
    global_idx = []
    for idx, data in enumerate(test_data):
        if data > 0:
            counter1.append(data)
            index.append(idx)
        else:
            if(len(counter1) != 0):
                global_peak.append(max(counter1))
                index.append(idx)
                global_idx.append(index)
            counter1.clear()
            index.clear()
        index.append(1) # <-- for demonstration
    return global_peak, global_idx

global_peaks(test_data)

# Output
([35, 320, 67, 4, 98], [[1], [1], [1], [1], [1]])

One problem comes with appending a list (global_idx.append(index)), which is a mutable object. You are appending a reference to this list so your output will show whatever is within this list at the moment of outputting.
What you need to use instead is a copy of that list (index.copy()), though this still does not give you the result you need.
Why should these lines give you the corresponding index

index.append(idx)
global_idx.append(index)

This should give you its corresponding index:

max_idx = index[counter1.index(max(counter1))]

One comment on your general approach: Be aware that if you have 2 or more local maxima within a region of only positive values, you would only find a single one. Is that really what you want?

The full code looks like this:

def global_peaks(test_data):
    counter1 = []
    index = []
    global_peak = []
    global_idx = []
    for idx, data in enumerate(test_data):
        if data > 0:
            counter1.append(data)
            index.append(idx)                                    
        else:
            if(len(counter1) != 0):
                global_peak.append(max(counter1))
                max_idx = index[counter1.index(max(counter1))] # <- changed 
                global_idx.append(max_idx) # <- changed
            counter1.clear()
            index.clear()
    return global_peak, global_idx

#Output
globla_peaks(test_data)
([35, 320, 67, 4, 98], [1, 7, 15, 19, 24])

Answered By: Flow
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.