Matplotlib Animations — Core Concepts
Matplotlib’s animation module creates animations by repeatedly updating a figure. There are two main approaches: FuncAnimation calls a function on each frame to update the plot, and ArtistAnimation plays a pre-built list of frames. Both produce animations that can be displayed in notebooks, saved as MP4/GIF, or embedded in web pages.
FuncAnimation: The Workhorse
FuncAnimation is the primary animation tool. It takes a figure, an update function, and a frame iterator. On each frame, it calls your function, which modifies the plot’s data or appearance.
The typical pattern has three parts:
- Setup — create the figure, axes, and initial plot elements (lines, scatter, bars)
- Init function — set the empty starting state (optional but recommended)
- Update function — receives the frame value and modifies the plot elements
The update function is the core of your animation. For a moving line, it might update the line’s y-data. For a growing scatter, it might add new points. For morphing bars, it might change bar heights.
The key insight is that you don’t redraw from scratch on each frame — you modify existing plot elements. This is what makes animations fast. When you create a Line2D object with ax.plot(), you keep a reference to it and call line.set_ydata(new_values) in your update function.
ArtistAnimation: Pre-Built Frames
ArtistAnimation takes a list where each item is a list of artists (plot elements) for that frame. You pre-create all frames, then ArtistAnimation cycles through them.
This approach is simpler for cases where frames are independent — like showing a sequence of images, or where each frame requires a completely different set of drawn objects. The downside is that all frames must be created upfront, using more memory.
Frame Sources and Timing
FuncAnimation accepts a frames parameter that can be:
- An integer — frames 0, 1, 2, …, n-1
- An iterable — any sequence of values passed to the update function
- A generator — for potentially infinite animations
- None — frames count up indefinitely
The interval parameter sets milliseconds between frames. At interval=50, you get 20 FPS. At interval=16, roughly 60 FPS. For most data animations, 20-30 FPS looks smooth without wasting computation.
repeat=True (default) loops the animation. Set repeat=False for one-shot animations.
What You Can Animate
Almost any Matplotlib element can be animated by updating its properties:
- Lines:
line.set_data(x, y)orline.set_ydata(y) - Scatter points:
scatter.set_offsets(xy_array) - Bar heights:
bar.set_height(value)on each Rectangle patch - Text:
text.set_text("new label") - Axis limits:
ax.set_xlim(new_min, new_max) - Colors:
scatter.set_array(new_colors)for colormapped data - Titles:
ax.set_title(f"Frame {i}")
Saving Animations
Matplotlib uses writer backends to save animations:
- PillowWriter — saves GIF files, built-in, no extra install
- FFMpegWriter — saves MP4/WebM/AVI, requires ffmpeg installed
- HTMLWriter — creates HTML with embedded JavaScript player
- ImageMagickWriter — alternative GIF writer
The save call looks like: anim.save('output.mp4', writer='ffmpeg', fps=30, dpi=100). DPI and figure size determine the output resolution. For web use, 720p at 100 DPI is typically sufficient. For presentations, bump to 150 DPI.
Notebook Display
In Jupyter notebooks, set %matplotlib notebook or use from IPython.display import HTML; HTML(anim.to_jshtml()) to display interactive animations inline. The to_jshtml() method creates an HTML5 player with play/pause controls and a frame slider.
Common Misconception
Many people think they need to call ax.clear() and redraw everything on each frame. This works but is slow — redrawing axes, tick marks, and labels every frame wastes time. Instead, update only the data that changes by keeping references to plot elements and modifying them in place. The blit=True option takes this further by only redrawing changed regions.
When to Animate vs. Use Interactive Plots
Animation is best for time-evolving data, presentations, social media content, and cases where the viewer should see the progression. Interactive plots (Bokeh, Plotly) are better when the user needs to explore specific moments rather than watch a sequence. Both can coexist — animate in Matplotlib for the story, then provide an interactive Bokeh version for drill-down.
One thing to remember: Matplotlib animations work by updating existing plot elements frame-by-frame (not redrawing from scratch), controlled by FuncAnimation’s update function, then saved to MP4/GIF via writer backends.
See Also
- Python Bokeh Interactive Plots How Bokeh turns boring static charts into clickable, zoomable pictures you can play with in your browser.
- Python Datashader Big Data Viz How Datashader draws millions of data points without crashing your computer or making an unreadable blob.
- Python Holoviews Declarative How HoloViews lets you describe what you want to see instead of telling the computer every drawing step.
- Python Matplotlib 3d Plotting How Matplotlib adds a third dimension to your charts so you can see data from all angles like a 3D video game.
- Python Panel Dashboards How Panel turns your Python charts and widgets into real dashboards that anyone can use in a browser.