I am graphing out positions in a star cluster, my data is in a dataframe with x,y,z positions as well as a time index.
I am able to produce a 3d scatter plot and was
The scatter plot in 3D is a mpl_toolkits.mplot3d.art3d.Path3DCollection
object. This provides an attribute _offsets3d
which hosts a tuple (x,y,z)
and can be used to update the scatter points' coordinates. Therefore it may be beneficial not to create the whole plot on every iteration of the animation, but instead only update its points.
The following is a working example on how to do this.
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()
This solution does not allow for blitting. However, depending on the usage case, it may not be necessary to use a scatter plot at all; using a normal plot
might be equally possible, which allows for blitting - as seen in the following example.
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()
If using Jupyter Notebook remember to use %matplotlib notebook
don't use %matplotlib inline
.