Skip to content Skip to sidebar Skip to footer

Finding The Point Of A Slope Change As A Free Parameter- Python

Say I have two lists of data as follows: x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] y = [1, 2, 3, 4, 5, 6, 8, 10, 12, 14] That is, it's pretty clear that merely fitting a line to this da

Solution 1:

Here is a plot of your data:

enter image description here

You need to find two slopes (== taking two derivatives). First, find the slope between every two points (using numpy):

import numpy as np 
x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10],dtype=np.float)
y = np.array([1, 2, 3, 4, 5, 6, 8, 10, 12, 14],dtype=np.float)
m = np.diff(y)/np.diff(x)
print (m)
# [ 1.  1.  1.  1.  1.  2.  2.  2.  2.]

Clearly, slope changes from 1 to 2 in the sixth interval (between sixth and seventh points). Then take the derivative of this array, which tells you when the slope changes:

print (np.diff(m))
[ 0.  0.  0.  0.  1.  0.  0.  0.]

To find the index of the non-zero value:

idx = np.nonzero(np.diff(m))[0]
print (idx)
# 4

Since we took one derivative with respect to x, and indices start from zero in Python, idx+2 tells you that the slope is different before and after the sixth point.


Solution 2:

I'm not sure to understand very well what you want but you can see the evolution this way (derivative):

>>> y = [1, 2, 3, 4, 5, 6, 8, 10, 12, 14]
>>> dy=[y[i+1]-y[i] for i in range(len(y)-1)]
>>> dy
[1, 1, 1, 1, 1, 2, 2, 2, 2]

and then find the point where it change (second derivative):

>>> dpy=[dy[i+1]-dy[i] for i in range(len(dy)-1)]
>>> dpy
[0, 0, 0, 0, 1, 0, 0, 0]

if you want the index of this point :

>>> dpy.index(1)
4

that can give you the value of the last point before change of slope :

>>> change=dpy.index(1)
>>> y[change]
5

In your y = [1, 2, 3, 4, 5, 6, 8, 10, 12, 14] the change happen at the index [4] (list indexing start to 0) and the value of y at this point is 5.


Solution 3:

You can calculate the slope as the difference between each pair of points (the first derivative). Then check where the slope changes (the second derivative). If it changes, append the index location to idx, the collection of points where the slope changes.

Note that the first point does not have a unique slope. The second pair of points will give you the slope, but you need the third pair before you can measure the change in slope.

idx = []
prior_slope = float(y[1] - y[0]) / (x[1] - x[0])
for n in range(2, len(x)):  # Start from 3rd pair of points.
    slope = float(y[n] - y[n - 1]) / (x[n] - x[n - 1])
    if slope != prior_slope:
        idx.append(n)
    prior_slope = slope

>>> idx
[6]

Of course this could be done more efficiently in Pandas or Numpy, but I am just giving you a simple Python 2 solution.

A simple conditional list comprehension should also be pretty efficient, although it is more difficult to understand.

idx = [n for n in range(2, len(x)) 
       if float(y[n] - y[n - 1]) / (x[n] - x[n - 1]) 
       != float(y[n - 1] - y[n - 2]) / (x[n - 1] - x[n - 2])]

Solution 4:

Knee point might be a potential solution.

from kneed import KneeLocator
import numpy as np 
x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
y = np.array([1, 2, 3, 4, 5, 6, 8, 10, 12, 14])
kn = KneeLocator(x, y, curve='convex', direction='increasing') 
# You can use array y to automatically determine 'convex' and 'increasing' if y is well-behaved
idx = (np.abs(x - kn.knee)).argmin()

>>> print(x[idx], y[idx])
6 6

Post a Comment for "Finding The Point Of A Slope Change As A Free Parameter- Python"