在这里非常有用的概念是由矩阵 A
执行的向量 v
的线性变换。如果你把你的散点看作从 (0,0) 起始的向量的顶点,那么旋转它们到任意角度 theta
就非常容易了。一个执行这种旋转的角度为theta
的矩阵是:
A = [[cos(theta) -sin(theta]
[sin(theta) cos(theta)]]
显然,当θ角度为90度时,会导致
A = [[ 0 1]
[-1 0]]
为了应用旋转,您只需要执行矩阵乘法w = A v
因此,当前目标是将存储在m
中的向量与x、y坐标点m [0],m [1]
进行矩阵乘法运算,旋转后的向量将存储在m2
中。以下是相关代码。请注意,我已经转置了m
以便更轻松地计算矩阵乘法(使用@
进行计算),而旋转角度为逆时针90度。
import numpy as np
import matplotlib.pyplot as plt
xx = np.array([-0.51, 51.2])
yy = np.array([0.33, 51.6])
means = [xx.mean(), yy.mean()]
stds = [xx.std() / 3, yy.std() / 3]
corr = 0.8
covs = [[stds[0]**2 , stds[0]*stds[1]*corr],
[stds[0]*stds[1]*corr, stds[1]**2]]
m = np.random.multivariate_normal(means, covs, 1000).T
plt.scatter(m[0], m[1])
theta_deg = 90
theta_rad = np.deg2rad(theta_deg)
A = np.matrix([[np.cos(theta_rad), -np.sin(theta_rad)],
[np.sin(theta_rad), np.cos(theta_rad)]])
m2 = np.zeros(m.T.shape)
for i,v in enumerate(m.T):
w = A @ v.T
m2[i] = w
m2 = m2.T
plt.scatter(m2[0], m2[1])
这导致了旋转的散点图:
通过线性变换,您可以确保旋转版本恰好逆时针旋转90度。
编辑
要找到旋转角度,使散点图与x轴对齐的方法是使用
numpy.polyfit
找到散点数据的线性近似。这会提供y轴截距
b
和
slope
的线性函数。然后使用
arctan
函数获取斜率的旋转角度,并像之前一样计算变换矩阵。您可以通过将以下部分添加到代码中来执行此操作。
slope, b = np.polyfit(m[1], m[0], 1)
x = np.arange(min(m[0]), max(m[0]), 1)
y_line = slope*x + b
plt.plot(x, y_line, color='r')
theta_rad = -np.arctan(slope)
并得到您正在寻找的图形结果
编辑2
由于@Peter Leimbigler指出numpy.polyfit
无法找到散点数据的正确全局方向,因此我想您可以通过平均数据的x
和y
部分来获得平均斜率。这是为了找到另一个斜率,称为slope2
(现在以绿色表示)以应用旋转。所以简单地说,
slope, b = np.polyfit(m[1], m[0], 1)
x = np.arange(min(m[0]), max(m[0]), 1)
y_line = slope*x + b
slope2 = np.mean(m[1])/np.mean(m[0])
y_line2 = slope2*x + b
plt.plot(x, y_line, color='r')
plt.plot(x, y_line2, color='g')
theta_rad = -np.arctan(slope2)
通过使用旋转矩阵进行线性变换,您可以得到以下结果: