简体   繁体   中英

How to rotate a 1D line graph array in python/numpy by angle?

I'd like to rotate a line graph horizontally. So far, I have the target angle but I'm not able to rotate the graph array (the blue graph in the blot).

import matplotlib.pyplot as plt
import numpy as np

x = [5, 6.5, 7, 8, 6, 5, 3, 4, 3, 0]
y = range(len(x))
best_fit_line = np.poly1d(np.polyfit(y, x, 1))(y)

angle = np.rad2deg(np.arctan2(y[-1] - y[0], best_fit_line[-1] - best_fit_line[0]))
print("angle: " + str(angle))

plt.figure(figsize=(8, 6))
plt.plot(x)
plt.plot(best_fit_line, "--", color="r")
plt.show()

在此处输入图像描述

The target calculations of the array should look like this (please ignore the red line):

在此处输入图像描述

If you have some advice, please let me know. Thanks.

This question is very helpful, in particular the answer by @Mr Tsjolder. Adapting that to your question, I had to subtract 90 from the angle you calculated to get the result you want:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import transforms

x = [5, 6.5, 7, 8, 6, 5, 3, 4, 3, 0]
y = range(len(x))
best_fit_line = np.poly1d(np.polyfit(y, x, 1))(y)

angle = np.rad2deg(np.arctan2(y[-1] - y[0], best_fit_line[-1] - best_fit_line[0]))
print("angle: " + str(angle))

plt.figure(figsize=(8, 6))

base = plt.gca().transData
rotation = transforms.Affine2D().rotate_deg(angle - 90)

plt.plot(x, transform = rotation + base)
plt.plot(best_fit_line, "--", color="r", transform = rotation + base)

旋转图


Follow-up question : What if we just need the numerical values of the rotated points?

Then the matplotlib approach can still be useful. From the rotation object we introduced above, matplotlib can extract the transformation matrix, which we can use to transform any point:

# extract transformation matrix from the rotation object
M = transforms.Affine2DBase.get_matrix(rotation)[:2, :2]

# example: transform the first point
print((M * [0, 5])[:, 1])

[-2.60096617 4.27024297]

The slicing was done to get the dimensions we're interested in, since the rotation happens only in 2D. You can see that the first point from your original data gets transformed to (-2.6, 4.3), agreeing with my plot of the rotated graph above.

In this way you can rotate any point you're interested in, or write a loop to catch them all.

Arne's awnser is perfect if you like to rotate the graph with matplotlib. If not, you can take a look a this code:

import matplotlib.pyplot as plt
import numpy as np


def rotate_vector(data, angle):
    # source: 
    # https://datascience.stackexchange.com/questions/57226/how-to-rotate-the-plot-and-find-minimum-point    
    # 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 rotated_vector


x = [5, 6.5, 7, 8, 6, 5, 3, 4, 3, 0]
y = range(len(x))
best_fit_line = np.poly1d(np.polyfit(y, x, 1))(y)

angle = np.rad2deg(np.arctan2(y[-1] - y[0], best_fit_line[-1] - best_fit_line[0]))
print("angle:", angle)

# rotate blue line
d = np.hstack((np.vstack(y), np.vstack(x)))
xr = rotate_vector(d, -(angle - 90))

# rotate red line
dd = np.hstack((np.vstack(y), np.vstack(best_fit_line)))
xxr = rotate_vector(dd, -(angle - 90))

plt.figure(figsize=(8, 6))
plt.plot(xr[:, 1]) # or plt.plot(xr[:, 0], xr[:, 1])
plt.plot(xxr[:, 1], "--", color="r")
plt.show()

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM