pythonseabornkdeplot

How to find last minima in density curve


i can't find easy way to get minima related to a density curve. With this kind of data :

import matplotlib.pyplot as plt
from scipy.misc import electrocardiogram
from scipy.signal import find_peaks
import seaborn as sns
    test = [7, 7, 7, 7, 8, 7, 7, 7, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 7, 7, 8, 7, 7, 8, 7, 7, 8, 7, 8, 7, 7, 8, 7, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 8, 7, 4, 4, 7, 8, 7]
    sns.kdeplot(test)

enter image description here

i would like to get the last inflection point related to the last "peak", in this situation it would be a minima around x=8. I tried function like get_peaks but this is not doing the job because i need to get all the values after this last inflection point and in some situation, like this one :

test2 = [8, 7, 7, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 7, 7, 7, 7, 8, 12] 

get_peaks didn't give me the last number.

My idea would be to get the x position of the last minima and after being able to get all the number higher than the minima.


Solution

  • It is better to place your latest find_peaks() implementation. Here I am trying to get it using that function.

    import matplotlib.pyplot as plt
    from scipy.signal import find_peaks
    import seaborn as sns
    
    test = [7, 7, 7, 7, 8, 7, 7, 7, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 7, 7, 8, 7, 7, 8, 7, 7, 8, 7, 8, 7, 7, 8, 7, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 8, 7, 4, 4, 7, 8, 7]
    ax = sns.kdeplot(test)
    x = ax.lines[0].get_xdata() # Get the x data of the distribution
    y = ax.lines[0].get_ydata() # Get the y data of the distribution
    xy = [[x[i], y[i]] for i in range(len(x))]
    
    # find peak
    peak_coord = [xy[i] for i in find_peaks(y)[0]]
    sorted_peak = sorted(peak_coord, key=lambda x: x[1])
    
    # sort peak based on its `y` coord
    sorted_peak.reverse() # [[7.01539631380498, 0.7002187588539351], [7.921442255354041, 0.3685891140800782], [3.984828854140883, 0.043144074377544736]]
    
    # second peak
    second_peak = sorted_peak[1] # [7.921442255354041, 0.3685891140800782]
    
    plt.show()
    

    As you can see, I can get the second peak is in coord [7.921442255354041, 0.3685891140800782]