The world’s leading publication for data science, AI, and ML professionals.

How to Animate Plots in Python

Learn the basics of animating data to create dynamic visuals

Animated Plot [Created by Author]
Animated Plot [Created by Author]

Data is becoming more and more desired in today’s world. Companies and individuals use it to predict stock prices via Machine Learning, to track the health of an athlete, to study house prices in a particular city… the possibilities are endless. While raw data is fundamental, the story it can tell is far more important. It’s the job of engineers and data scientists to tell this story. Visuals can be one of the best way to convey an idea using data. Think, would you rather look at lines and lines of data or a couple plots that summarize it? Like most, you probably thought plots sounded better. Though not always necessary, adding animation to a plot could provide extra meaning to your storytelling.

By the end of this article, you should be able to recreate the above plot AND use this framework to create your own beautiful animations.

Photo by Emile Perron on Unsplash
Photo by Emile Perron on Unsplash

For this article, I’ll be assuming you have a little background with Python and how to perform basic data manipulation and plotting. Keep in mind, this is not the only way to use Python’s animation capability, so share your method below if you have other ideas! We will be using three-dimensional lines and scatter points to create a trajectory, but these concepts can be expanded into other plot types such as two-dimensional lines, bar graphs, pie charts, contours, etc.

Importing Packages

Python has a vast amount of libraries for data analysis, so we will make use of a couple of those. Let’s start a new script and import our required packages for this project:

# Importing Packages
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import animation
  • NumPy will be used for creating numerical arrays and using trigonometric functions (defined as np for ease of calling)
  • Pyplot from Matplotlib will be used for plotting graphics (defined as plt for ease of calling)
  • Axes3D will be used to create three-dimensional axes for our plot
  • animation from Matplotlib will be used to create our animation by repeatedly calling a function that we will define later on

Creating a Data Set

Before we can even think about plotting anything, we need to create our data to plot. For this part, I created some position data using the sine function and a time array that runs from 0 to 20 (I arbitrarily label it as seconds in the animation).

# Time Array
t = np.linspace(0, 20, 100)

# Position Arrays
x = np.sin(np.pi/5 * t)
y = np.sin(np.pi/3 * t)
z = np.linspace(0, 100, 100)

# Setting up Data Set for Animation
dataSet = np.array([x, y, z])  # Combining our position coordinates
numDataPoints = len(t)

I think this section is pretty self-explanatory. You can mess around with the time and position arrays to create new trajectories. The dataSet and numDataPoints variables will be used in our animation function, which we will define next.

Animation Function

To animate our figure, we will be using a function, called FuncAnimation, from the imported animation class. You can access the documentation on these two here. FuncAnimation requires us to create our own function that updates the lines, points, etc., which we will define as _animatefunc.

def animate_func(num):
    ax.clear()  # Clears the figure to update the line, point,   
                # title, and axes
    # Updating Trajectory Line (num+1 due to Python indexing)
    ax.plot3D(dataSet[0, :num+1], dataSet[1, :num+1], 
              dataSet[2, :num+1], c='blue')
    # Updating Point Location 
    ax.scatter(dataSet[0, num], dataSet[1, num], dataSet[2, num], 
               c='blue', marker='o')
    # Adding Constant Origin
    ax.plot3D(dataSet[0, 0], dataSet[1, 0], dataSet[2, 0],     
               c='black', marker='o')
    # Setting Axes Limits
    ax.set_xlim3d([-1, 1])
    ax.set_ylim3d([-1, 1])
    ax.set_zlim3d([0, 100])

    # Adding Figure Labels
    ax.set_title('Trajectory nTime = ' + str(np.round(t[num],    
                 decimals=2)) + ' sec')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('z')

We start by noticing the num variable being passed into _animatefunc. This is an index for the current animation step. When we pass _animatefunc to FuncAnimation, it will iterate our num variable. We can use that variable to iterate through our dataSet that we created earlier.

The function starts by clearing the figure. This removes the line, point, origin, axis labels, and title. It then adds the updated trajectory line (from 0 to num) and point location (at step num). Our origin remains constant in this figure, so you’ll notice that num does not show up since we are not changing the origin. Next, the function defines our unchanging axis limits. You can remove the axis limits if you want the axes to change as your numbers increase (causing the axes to be dynamic).

Finally, the function defines our title and our axis labels. The labels are straightforward, just our x, y, and z for Cartesian coordinates. As a little bit of extra functionality, we have a dynamic title that shows the trajectory time array, t. We are displaying it (rounding to the second decimal place) and updating it each iteration. Note, these are not real-time seconds.

Plotting our Animation

The last step is actually plotting our animation using FuncAnimation. We start by creating our figure object with three-dimensional axes. We then use FuncAnimation, which takes the figure, our animation function created earlier, an interval value, and a frames value as inputs. Interval is the delay between frames in milliseconds, and frames is simply the number of frames you wish to show. These last two are optional arguments, but I like to include them if I want to adjust how the animation looks.

# Plotting the Animation
fig = plt.figure()
ax = plt.axes(projection='3d')
line_ani = animation.FuncAnimation(fig, animate_func, interval=100,   
                                   frames=numDataPoints)
plt.show()

You can run the code, and if done correctly, your plot should look something like the following (the speed of the point may be different):

Trajectory Animation [Created by Author]
Trajectory Animation [Created by Author]

Saving our Animation (Optional)

If you want to save your animation as a .gif file, you can use the following code to do just that.

# Saving the Animation
f = r"c://Users/(Insert User)/Desktop/animate_func.gif"
writergif = animation.PillowWriter(fps=numDataPoints/6)
line_ani.save(f, writer=writergif)

You need to pick a location to save it and store it as the f variable. You can adjust the frames per second, fps, variable in PillowWriter. I divided the numDataPoints variable, which was defined as the number of frames in FuncAnimation, by 6 to have the animation be 6 seconds long.


That’s all for this article. Thank you for reading! If you don’t want to miss out on more Python and engineering articles, give me a follow and subscribe to my emails. I’ve written a few other articles, so check those out as well!


Related Articles