avatarZack Fizell

Summary

This article provides a tutorial on how to create animated plots in Python using libraries such as NumPy, Matplotlib, and its animation toolkit, demonstrating the process with a 3D trajectory example.

Abstract

The article "How to Animate Plots in Python" guides readers through the process of adding dynamic visuals to data storytelling by animating plots. It assumes a basic understanding of Python and data manipulation, focusing on the use of NumPy for numerical arrays, Matplotlib for plotting, and its animation capabilities to create a three-dimensional animated trajectory. The tutorial covers the importation of necessary packages, the generation of a synthetic data set using trigonometric functions, and the definition of an animation function that updates the plot iteratively. The article concludes with instructions on how to display and save the resulting animation as a GIF, emphasizing the importance of visuals in data communication and encouraging readers to explore and share their own animated plot creations.

Opinions

  • The author believes that animating plots can add extra meaning to data storytelling, making the narrative more engaging.
  • They suggest that while raw data is crucial, the way it is presented through visuals is even more important for conveying ideas effectively.
  • The author encourages experimentation with the provided code and data sets, inviting readers to create and share their own beautiful animations beyond the scope of the tutorial.
  • They imply that the methods shown are not the only way to animate plots in Python, indicating a rich ecosystem of possible techniques and libraries within the Python data science community.
  • The author values the reader's engagement with the content, prompting them to follow and subscribe for more Python and engineering articles, indicating a commitment to building a community of learners and practitioners.

How to Animate Plots in Python

Learn the basics of animating data to create dynamic visuals

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

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 animate_func.

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 animate_func. This is an index for the current animation step. When we pass animate_func 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]

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!

Python
Programming
Machine Learning
Technology
Science
Recommended from ReadMedium