Matplotlib三维散点动画

2024-09-27 09:37:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在绘制星团中的位置,我的数据在一个数据框中,包含x、y、z位置和时间索引。

我能够生成一个三维散点图,并试图生成一个旋转图——我已经取得了一些成功,但在动画API中苦苦挣扎。

如果我的“update_graph”函数只返回一个新的ax.scatter(),则除非我重新生成整个图,否则旧的函数将保持绘制状态。这似乎效率不高。另外,我必须将间隔设置得相当高,否则动画会每隔一帧“跳跃”,因此它会说我的性能相当差。最后,我不得不使用“blit=False”,因为我无法获得三维散点图的迭代器。显然“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()

Tags: 数据sample函数datatitlefig绘制update
2条回答

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可能同样可行,这允许进行分块-如下面的示例所示。

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()

如果使用Jupyter笔记本,记得使用%matplotlib notebook不要使用%matplotlib inline

相关问题 更多 >

    热门问题