3

I have a question related to finding maxima or more preciseley discontinuities in a numpy array? My exemplary data looks for example like this

a = np.array([3,4,5,8,7,6,5,4,1])

In general, I am interested in every maximum/jump in the data. For array a, I want to detect the 8 since it is a maximum (growing numbers on the left side and decreasing numbers on the right) and the value of 4, since the data drops after this value. Until now, I have used scipy.signal.argrelextrema with np.greater to detect maxima, but I am not able to detect these jumps/discontinuities. For the data I am looking at, only a jump towards smaller values can occur not the opposite. Is there an easy pythonic way to detect these jumps?

Mr. T
  • 11,960
  • 10
  • 32
  • 54
Jan
  • 57
  • 5
  • so jumps discontinuities are defined as a difference of more than 1 ? `np.diff(a)` may help you. – Yacola Nov 20 '20 at 12:32
  • Let us assume for the moment that i can assing a threshold value which could be one. – Jan Nov 20 '20 at 12:34
  • @Jan there's a slight difference between `pythonic` and `numpyic`. I face that a majority of `numpyic` methods are more readable and faster that `pythonic` ones (like loops, comprehensions etc.) – mathfux Nov 20 '20 at 12:59
  • @mathfux you are right. I think we are always looking for an numpyic solution since it is in most cases faster ;) – Jan Nov 23 '20 at 09:44

3 Answers3

4

Let's try this:

threshold = 1
a = np.array([3, 4, 5, 8, 7, 6, 5, 4, 1])
discontinuities_idx = np.where(abs(np.diff(a))>threshold)[0] + 1

np.diff(a) gives the difference between every component of a:

>>> array([ 1,  1,  3, -1, -1, -1, -1, -3])

From then np.where(abs(np.diff(a))>threshold)[0] is applied to find where detected discontinuities are (above user specified threshold in terms of absolute difference). Finally, you may add +1 to compensate for n=1 difference idx if needed (see np.diff kwargs) depending on which side of the discontinuities you need to be.

>>> discontinuities_idx
>>> array([3, 8])
>>> a[discontinuities_idx]
>>> array([8, 1])
Yacola
  • 2,873
  • 1
  • 10
  • 27
1

It sounds like mathemathical analysis where you need to define some conditions like a'(x)>0 or a'(x)<0. So you can mask them:

a = np.array([3,4,5,8,7,8,6,5,4,9,2,9,9,7])
mask1 = np.diff(a) > 0
mask2 = np.diff(a) < 0
>>> np.flatnonzero(mask1[:-1] & mask2[1:]) + 1
array([3, 5, 9], dtype=int64)

It returns indices of items where maxima is met.

mathfux
  • 5,759
  • 1
  • 14
  • 34
0

You can try this:

import numpy as np
import math
a = np.array([3,4,5,8,7,6,5,4,1])
MaxJump = np.diff(a)
print(MaxJump)
print(len(MaxJump))
MaxJump1 = []
for i in range (len(MaxJump)):
    MaxJump1.append(math.fabs(MaxJump[i]))
print(MaxJump1)
MaxJump3 = np.max(MaxJump1)
print(MaxJump3)
Marcelo
  • 77
  • 9