hanzgs
hanzgs

Reputation: 1616

How to find Optimum value from the plot values python?

I have a python dict

{'kValues': [2,   3,   4,   5,   6,   7,   8,   9,   10],
  'WSS': [21455, 5432, 4897, 4675, 4257, 3954, 3852, 3756, 3487],
  'SS': [0.75, 0.85, 0.7, 0.52, 0.33, 0.38, 0.42, 0.46, 0.47]}

When I plot kValues against WSS and SS, I get following line enter image description here

The optimum value of 1st plot is at k value = 3 and on 2nd plot is at k value = 3

How to extract that k value from the dictionary without visualizing the plots

Criteria - First plot always have a elbow, elbow point to be extracted, second plot always have a raise followed by a dip, that raise value to be extracted

Upvotes: 1

Views: 314

Answers (3)

hanzgs
hanzgs

Reputation: 1616

Found this wonderful python library for finding the optimum value

https://pypi.org/project/kneed/

from kneed import KneeLocator
kneedle = KneeLocator(kValues, WSS, S=1.0, curve="convex", direction="decreasing")
print(kneedle.knee)  # 3
print(kneedle.elbow)  # 3

curve and direction can be configured based on pattern

Upvotes: 1

SiP
SiP

Reputation: 1160

You can use the derivative to find the peak in the SS:

import numpy as np
k_ss = kValues[np.where(np.sign(np.diff(SS, append=SS[-1])) == -1)[0][0]]

diff calculates the difference between the elements (the derivative) and then we find the first place where the derivative changes sign (goes over the peak).

For WSS it's a bit more complicated because you have to define a threshold, that would define an elbow, you could take a few examples from your data and use that. Here is a code where the threshold is set to 1/10 of the max derivative:

d = np.diff(WSS, append=WSS[-1])
th = max(abs(d)) / 10
k_wss = kValues[np.where(abs(d) < th)[0][0]]

Other than that you can try to fit the data to an asymptotic curve and extract the constants

Upvotes: 0

Hiren Namera
Hiren Namera

Reputation: 424

You can use the angle between 3 points p1,p2, and p3 which will be only helpful, and a point that is near 90 degrees for the elbow and 0 for deep. I am sharing my code the normalization is the tricky.

import math
kValues= [1 , 2 ,   3,   4,   5,   6,   7,   8,   9,   10]
WSS= [81000,21455, 5432, 4897, 4675, 4257, 3954, 3852, 3756, 3487]
SS=[0.75, 0.85, 0.7, 0.52, 0.33, 0.38, 0.42, 0.46, 0.47]

#get all the angles between k values as x and WSS as y
angles=[]
#each WSS slab values
normalize_wss=2000
for i in range(1,len(WSS)-1,1):
    p1=(kValues[i-1]*normalize_wss,WSS[i-1])
    p2=(kValues[i]*normalize_wss,WSS[i])
    p3=(kValues[i+1]*normalize_wss,WSS[i+1])
    #find angle between 3 points p1,p2,p3
    angle1=math.degrees(math.atan2(p3[1]-p2[1],p3[0]-p2[0]))
    angle2=math.degrees(math.atan2(p1[1]-p2[1],p1[0]-p2[0]))
    angles.append([angle1-angle2])
print(angles)

Upvotes: 1

Related Questions