我正在绘制星团中的位置图,我的数据位于具有 x、y、z 位置以及时间索引的数据框中。
我能够制作 3d 散点图并尝试制作旋转图——我取得了一定的成功,但在动画 API 方面遇到了困难。
如果我的“update_graph”函数只返回一个新的 ax.scatter(),旧的将保持绘制状态,除非我重建整个图。这似乎效率低下。同样,我必须将我的间隔设置得相当高,否则我的动画每隔一帧“跳过”一次,所以它说我的表现相当糟糕。最后,我不得不使用“blit=False”,因为我无法获得 3d 散点图的迭代器。显然“graph.set_data()”不起作用,我可以使用“graph.set_3d_properties”,但这只允许我使用新的 z 坐标。
所以我拼凑了一条线索——(我使用的数据位于 https://www.kaggle.com/mariopasquato/star-cluster-simulations 滚动到底部)
另外我只绘制了 100 个点 (data=data[data.id<100])
我的(工作)代码如下:
def update_graph(num):
ax = p3.Axes3D(fig)
ax.set_xlim3d([-5.0, 5.0])
ax.set_xlabel('X')
ax.set_ylim3d([-5.0, 5.0])
ax.set_ylabel('Y')
ax.set_zlim3d([-5.0, 5.0])
ax.set_zlabel('Z')
title='3D Test, Time='+str(num*100)
ax.set_title(title)
sample=data0[data0['time']==num*100]
x=sample.x
y=sample.y
z=sample.z
graph=ax.scatter(x,y,z)
return(graph)
fig = plt.figure()
ax = p3.Axes3D(fig)
# Setting the axes properties
ax.set_xlim3d([-5.0, 5.0])
ax.set_xlabel('X')
ax.set_ylim3d([-5.0, 5.0])
ax.set_ylabel('Y')
ax.set_zlim3d([-5.0, 5.0])
ax.set_zlabel('Z')
ax.set_title('3D Test')
data=data0[data0['time']==0]
x=data.x
y=data.y
z=data.z
graph=ax.scatter(x,y,z)
# Creating the Animation object
line_ani = animation.FuncAnimation(fig, update_graph, 19,
interval=350, blit=False)
plt.show()
最佳答案
3D 中的散点图 是一个mpl_toolkits.mplot3d.art3d.Path3DCollection
对象。这提供了一个属性 _offsets3d
,它包含一个元组 (x,y,z)
,可用于更新散点的坐标。因此,最好不要在动画的每次迭代中都创建整个图,而是只更新它的点。
以下是有关如何执行此操作的工作示例。
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation
import pandas as pd
a = np.random.rand(2000, 3)*10
t = np.array([np.ones(100)*i for i in range(20)]).flatten()
df = pd.DataFrame({"time": t ,"x" : a[:,0], "y" : a[:,1], "z" : a[:,2]})
def update_graph(num):
data=df[df['time']==num]
graph._offsets3d = (data.x, data.y, data.z)
title.set_text('3D Test, time={}'.format(num))
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
title = ax.set_title('3D Test')
data=df[df['time']==0]
graph = ax.scatter(data.x, data.y, data.z)
ani = matplotlib.animation.FuncAnimation(fig, update_graph, 19,
interval=40, blit=False)
plt.show()
此解决方案不允许 blitting。但是,根据使用情况,可能根本不需要使用散点图;使用普通 plot
可能同样可行,这允许 blitting - 如以下示例所示。
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation
import pandas as pd
a = np.random.rand(2000, 3)*10
t = np.array([np.ones(100)*i for i in range(20)]).flatten()
df = pd.DataFrame({"time": t ,"x" : a[:,0], "y" : a[:,1], "z" : a[:,2]})
def update_graph(num):
data=df[df['time']==num]
graph.set_data (data.x, data.y)
graph.set_3d_properties(data.z)
title.set_text('3D Test, time={}'.format(num))
return title, graph,
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
title = ax.set_title('3D Test')
data=df[df['time']==0]
graph, = ax.plot(data.x, data.y, data.z, linestyle="", marker="o")
ani = matplotlib.animation.FuncAnimation(fig, update_graph, 19,
interval=40, blit=True)
plt.show()
关于python - Matplotlib 3D 散点动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41602588/