我绘制了一些3D数据的特征向量,想知道目前(已经)有没有一种方法可以把箭头放在线上?如果有人能给我一个提示,那就太棒了。
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
####################################################
# This part is just for reference if
# you are interested where the data is
# coming from
# The plot is at the bottom
#####################################################
# Generate some example data
mu_vec1 = np.array([0,0,0])
cov_mat1 = np.array([[1,0,0],[0,1,0],[0,0,1]])
class1_sample = np.random.multivariate_normal(mu_vec1, cov_mat1, 20)
mu_vec2 = np.array([1,1,1])
cov_mat2 = np.array([[1,0,0],[0,1,0],[0,0,1]])
class2_sample = np.random.multivariate_normal(mu_vec2, cov_mat2, 20)
# concatenate data for PCA
samples = np.concatenate((class1_sample, class2_sample), axis=0)
# mean values
mean_x = mean(samples[:,0])
mean_y = mean(samples[:,1])
mean_z = mean(samples[:,2])
#eigenvectors and eigenvalues
eig_val, eig_vec = np.linalg.eig(cov_mat)
################################
#plotting eigenvectors
################################
fig = plt.figure(figsize=(15,15))
ax = fig.add_subplot(111, projection='3d')
ax.plot(samples[:,0], samples[:,1], samples[:,2], 'o', markersize=10, color='green', alpha=0.2)
ax.plot([mean_x], [mean_y], [mean_z], 'o', markersize=10, color='red', alpha=0.5)
for v in eig_vec:
ax.plot([mean_x, v[0]], [mean_y, v[1]], [mean_z, v[2]], color='red', alpha=0.8, lw=3)
ax.set_xlabel('x_values')
ax.set_ylabel('y_values')
ax.set_zlabel('z_values')
plt.title('Eigenvectors')
plt.draw()
plt.show()
3条答案
按热度按时间camsedfj1#
要在3D绘图中添加箭头补丁,简单的解决方案是使用
/matplotlib/patches.py
中定义的FancyArrowPatch
类。然而,它只适用于2D绘图(在编写本文档时),因为它的posA
和posB
假定为长度为2的元组。因此,我们创建了一个新的箭头补丁类,命名为
Arrow3D
,它继承自FancyArrowPatch
。我们只需要覆盖它的posA
和posB
。要做到这一点,我们用posA
和(0,0)
的posB
初始化Arrow3d
。然后使用proj3d.proj_transform()
将3D坐标xs, ys, zs
从3D投影到2D,并使用.set_position()
方法将生成的2D坐标分配给posA
和posB
,替换(0,0)
。这样,我们就可以使用3D箭头。投影步骤进入
.draw
方法,该方法覆盖FancyArrowPatch
对象的.draw
方法。这可能看起来像是一个黑客。然而,
mplot3d
目前只提供(再次,只提供)简单的3D绘图能力,通过提供3D-2D投影,基本上在2D中完成所有绘图,这并不是真正的3D。实际绘制。注意,我们只需要更改一行代码,即添加一个新的箭头艺术家:
请查看引发此问题的this post,了解更多详细信息。
shyt4zoc2#
另一个选项:您还可以使用
plt.quiver
函数,它允许您非常轻松地生成箭头矢量,而无需任何额外的导入或类。若要复制您的范例,您可以取代:
与:
gjmwrych3#
新版本的matplotlib抛出了
AttributeError: 'Arrow3D' object has no attribute 'do_3d_projection'
,但Arrow3D
的定义是旧的。这里有几条注解提到了这个问题,但仍然不清楚。你必须添加函数do_3d_projection()
,而不再需要draw()
。当前代码如下所示:帮助来自github。