Another example here
In [1]:
%pylab inline
import scipy as sp
import seaborn as sns
from scipy.interpolate import UnivariateSpline
sns.set_style('white')
def draw_plot(X, Y, knee_point=None):
plt.plot(X, Y)
if knee_point:
plt.axvline(x=knee_point, color='k', linestyle='--')
In [2]:
X = [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000]
Y = [2314, 802, 519, 417, 358, 318, 302, 284, 280]
n = len(X)
S = 1
In [3]:
def _locate(Y_d, T_lm, maxima_ids):
n = len(Y_d)
for j in range(0, n):
for index, i in enumerate(maxima_ids):
if j <= i:
continue
if Y_d[j] <= T_lm[index]:
return index
def find_knee_point(X, Y, S):
n = len(X)
spl = UnivariateSpline(X, Y)
X_s = np.linspace(np.min(X), np.max(X), n)
Y_s = spl(X_s)
X_sn = (X_s - np.min(X_s)) / (np.max(X_s) - np.min(X_s))
Y_sn = (Y_s - np.min(Y_s)) / (np.max(Y_s) - np.min(Y_s))
X_d = X_sn
Y_d = Y_sn - X_sn
X_lm = []
Y_lm = []
maxima_ids = []
for i in range(1, n - 1):
if (Y_d[i] > Y_d[i - 1] and Y_d[i] > Y_d[i + 1]) or (np.sign(Y_d[i + 1]) != np.sign(Y_d[i - 1])):
X_lm.append(X_d[i])
Y_lm.append(Y_d[i])
maxima_ids.append(i)
print(Y_lm)
T_lm = Y_lm - S * np.sum(np.diff(X_sn)) / (n - 1)
knee_point_index = _locate(Y_d, T_lm, maxima_ids)
knee_point = X_lm[knee_point_index] * (np.max(X_s) - np.min(X_s)
) + np.min(X_s)
return knee_point, Y_d
In [4]:
knee_point, _ = find_knee_point(X, Y, S)
draw_plot(X, Y, knee_point)
In [ ]: