问题:如何用python绘制能够旋转的三维动图
解决:
Code
import matplotlib.pyplot as plt
from matplotlib import animation
import numpy as np
def componential_plot_animated_3d(reduced_data, labels, pc, variable):
"""draw a animated componential plot in 3d for three principle components
:param reduced_data: data processed by PCA
:param labels: labels of original dataset
:param pc: all the principle components
:param variable: the name of the variables of the data set
"""
fig = plt.figure(1, figsize=(14, 12))
ax = plt.axes(projection='3d')
legend = [] #
classes = np.unique(labels) # label type
n = pc.shape[1]
# colors = ['g', 'r', 'y']
# markers = ['o', '^', 'x']
x = reduced_data[:, 0] # variable contributions for PC1
y = reduced_data[:, 1] # variable contributions for PC2
z = reduced_data[:, 2] # variable contributions for PC3
scalex = 1.0/(x.max() - x.min())
scaley = 1.0/(y.max() - y.min())
scalez = 1.0/(z.max() - z.min())
def init():
# A function used to draw a clear and initial frame
# draw a data point projection plot that is projected to
# a three-dimensional space using normal PCA
for i, label in enumerate(classes):
ax.scatter3D(x[labels==label] * scalex,
y[labels==label] * scaley,
z[labels==label] * scalez,
linewidth=0.01)
# hyperparameter in plt.scatter(): c=colors[i], marker=markers[i]
legend.append("Label: {}".format(label))
ax.legend(legend)
# plot arrows as the variable contribution,
# each variable has a score for PC1, for PC2 and for PC3 respectively
for i in range(n):
ax.quiver(0, 0, 0, pc[0, i], pc[1, i], pc[2, i], color='k', alpha=0.7,
linewidth=1, arrow_length_ratio=0.05)
ax.text(pc[0, i]*1.1, pc[1, i]*1.1, pc[2, i]*1.1, variable[i],
ha='center', va='center', color='k', fontsize=12)
ax.set_xlabel("$PC1$")
ax.set_ylabel("$PC2$")
ax.set_zlabel("$PC3$")
plt.title("Compositional Plot in 3 Dimension")
plt.grid()
def rotate(angle):
ax.view_init(elev=10, azim=angle)
# animate, frames=values will be passed to rotate, interval means the the delay between frames in milliseconds
rot_animation = animation.FuncAnimation(fig, rotate, init_func=init,
frames=np.arange(0,362,2), interval=50)
# save the animat
rot_animation.save('./images/animated_3d_composiontion_plot.gif', dpi=80, writer='imagemagick')
- 需要定义一个函数以获取特定的动画:
def rotate(angle):
ax.view_init(elev=10, azim=angle)
- 然后使用matplotlib动画,这将调用与
frames
参数作为角度和与50ms
的间隔旋转功能
rot_animation = animation.FuncAnimation(fig, rotate, init_func=init,
frames=np.arange(0,362,2), interval=50)
- 所以这将导致360°的轮换,其中2°步每个耗费时间50ms。将动画保存为gif文件:
rot_animation.save('./images/animated_3d_composiontion_plot.gif', dpi=80, writer='imagemagick')
参考资料: