-1
$\begingroup$

I want to rotate the below curve to 45 degree and then find the minimum point. enter image description here

For this, I have tried with below code:

def rotate_vector(data, angle):
    theta = np.radians(angle)
    co = np.cos(theta)
    si = np.sin(theta)
    rotation_matrix = np.array(((co,-si), (si, co)))
    return np.matmul(rotation_matrix, data)


rotated_vector = rotate_vector(data, -45)
elbow = rotated_vector.min()

But what I get is this curve: enter image description here

$\endgroup$
  • $\begingroup$ Sorry but... Why?? $\endgroup$ – Erwan Aug 8 at 16:46
  • $\begingroup$ @Erwan I want to get the point where the curve starts changing so as to find threshold. $\endgroup$ – Sajjadmanal Aug 9 at 5:28
  • $\begingroup$ @Sajjadmanal based on the code from my answer in the original post, I created a python package called kneebow which provides all the functionality plus some convenience methods and axis scaling. $\endgroup$ – georg-un Aug 9 at 22:59
  • 1
    $\begingroup$ @georg-un Wow. You made a whole library out of this question. Amazing..! $\endgroup$ – Sajjadmanal Aug 10 at 18:51
1
$\begingroup$

Please refer to the original post.

The problem was the np.radians(angle). I corrected that.

Edit: The problem was not the radian conversion but the different scales of the x- and y-axis. 45 degrees rotation was simply not enough.

Let's use a modified version of the code you posted:

def rotate_vector(data, angle):
    # make rotation matrix
    theta = np.radians(angle)
    co = np.cos(theta)
    si = np.sin(theta)
    rotation_matrix = np.array(((co, -si), (si, co)))
    # rotate data vector
    rotated_vector = data.dot(rotation_matrix)
    # return index of elbow
    return rotated_vector

Now, we define a square as test-data:

data = np.array([
    [1, 0], [2, 0], [3, 0], [4, 0], [5, 0],
    [0, 0], [0, 1], [0, 2], [0, 3], [0, 4], 
    [5, 1], [5, 2], [5, 3], [5, 4], [5, 5],
    [0, 5], [1, 5], [2, 5], [3, 5], [4, 5],
])

plt.scatter(data[:, 0], data[:, 1])

Plotting the data gives us the following figure:

enter image description here

Now, we rotate that vector using the function from above:

rotated_data = rotate_vector(data, 45)

plt.scatter(rotated_data[:, 0], rotated_data[:, 1])

If we plot the rotated data, we get the following figure:

enter image description here

So it does work. However, if we want to rotate the graph that you posted to find the minimum, we need to remember that the scales of the two axes are different. That means the graph may look like a 45° rotation would be enough while actually, it is not.

I corrected the original post again. Also, I added a method to find an approximate rotation angle to account for the different axis scales.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.