Animations with Matplotlib. Animations are an interesting way of... | by Parul Pandey | Towards Data Science

Animations are an interesting way of demonstrating a phenomenon. We as humans are always enthralled by animated and interactive charts rather than the static ones. Animations make even more sense when depicting time-series data like stock prices over the years, climate change over the past decade, seasonalities and trends since we can then see how a particular parameter behaves with time.
The above image is a simulation of Rain and has been achieved with Matplotlib library which is fondly known as the grandfather of python visualization packages. Matplotlib simulates raindrops on a surface by animating the scale and opacity of 50 scatter points. Today Python boasts of a large number of powerful visualization tools like Plotly, Bokeh, Altair to name a few. These libraries are able to achieve state of the art animations and interactiveness. Nonetheless, the aim of this article is to highlight one aspect of this library which isn’t explored much and that is Animations and we are going to look at some of the ways of doing that.
Matplotlib is a Python 2D plotting library and also the most popular one. Most of the people start their Data Visualisation journey with Matplotlib. One can generate plots, histograms, power spectra, bar charts, error charts, scatterplots, etc easily with matplotlib. It also integrates seamlessly with libraries like Pandas and Seaborn to create even more sophisticated visualizations.
Some of the nice features of matplotlib are:
It is designed like MATLAB hence switching between the two is fairly easy.
Comprises of a lot of rendering backends.
It can reproduce just about any plots( with a bit of effort).
Has been out there for over a decade, therefore, boasts of a huge user base.
However, there are also areas where Matplotlib doesn’t shine out so much and lags behind its powerful counterparts.
Matplotlib has an imperative API which is often overly verbose.
Sometimes poor stylistic defaults.
Poor support for web and interactive graphs.
Often slow for large & complicated data.
As for a refresher here is a Matplotlib Cheatsheet from Datacamp which you can go through to brush up your basics.
Python For Data Science Cheat Sheet

Matplotlib

Learn Python Interactively at www.DataCamp.com

Matplotlib

DataCamp

Learn Python for Data Science Interactively

Prepare The Data Also see Lists & NumPy

Matplotlib is a Python 2D plotting library which produces

publication-quality figures in a variety of hardcopy formats

and interactive environments across

platforms.

1

>>> import numpy as np

>>> x = np.linspace(0, 10, 100)

>>> y = np.cos(x)

>>> z = np.sin(x)

Show Plot

>>> plt.show()

Save Plot

Save figures

>>> plt.savefig('foo.png')

Save transparent figures

>>> plt.savefig('foo.png', transparent=True)

6

5

>>> fig = plt.figure()

>>> fig2 = plt.figure(figsize=plt.figaspect(2.0))

2 Create Plot

Plot Anatomy & Workflow

All plotting is done with respect to an Axes. In most cases, a

subplot will fit your needs. A subplot is an axes on a grid system.

>>> fig.add_axes()

>>> ax1 = fig.add_subplot(221) # row-col-num

>>> ax3 = fig.add_subplot(212)

>>> fig3, axes = plt.subplots(nrows=2,ncols=2)

>>> fig4, axes2 = plt.subplots(ncols=3)

Customize Plot

Colors, Color Bars & Color Maps

Markers

Linestyles

Mathtext

Text & Annotations

Limits, Legends & Layouts

The basic steps to creating plots with matplotlib are:

1 Prepare data 2 Create plot 3 Plot 4 Customize plot 5 Save plot 6Show plot

>>> import matplotlib.pyplot as plt

>>> x = [1,2,3,4]

>>> y = [10,20,25,30]

>>> fig = plt.figure()

>>> ax = fig.add_subplot(111)

>>> ax.plot(x, y, color='lightblue', linewidth=3)

>>> ax.scatter([2,4,6],

[5,15,25],

color='darkgreen',

marker='^')

>>> ax.set_xlim(1, 6.5)

>>> plt.savefig('foo.png')

>>> plt.show()

Step 3, 4

Step 2

Step 1

Step 3

Step 6

Plot Anatomy Workflow

4

Limits & Autoscaling

>>> ax.margins(x=0.0,y=0.1) Add padding to a plot

>>> ax.axis('equal') Set the aspect ratio of the plot to 1

>>> ax.set(xlim=[0,10.5],ylim=[-1.5,1.5]) Set limits for x-and y-axis

>>> ax.set_xlim(0,10.5) Set limits for x-axis

Legends

>>> ax.set(title='An Example Axes', Set a title and x-and y-axis labels

ylabel='Y-Axis', xlabel='X-Axis')

>>> ax.legend(loc='best') No overlapping plot elements

Ticks

>>> ax.xaxis.set(ticks=range(1,5), Manually set x-ticks

ticklabels=[3,100,-12,"foo"])

>>> ax.tick_params(axis='y', Make y-ticks longer and go in and out

direction='inout', length=10)

Subplot Spacing

>>> fig3.subplots_adjust(wspace=0.5, Adjust the spacing between subplots

hspace=0.3,

left=0.125,

right=0.9,

top=0.9,

bottom=0.1)

>>> fig.tight_layout() Fit subplot(s) in to the figure area

Axis Spines

>>> ax1.spines['top'].set_visible(False) Make the top axis line for a plot invisible

>>> ax1.spines['bottom'].set_position(('outward',10)) Move the bottom axis line outward

Figure

Axes

>>> data = 2 * np.random.random((10, 10))

>>> data2 = 3 * np.random.random((10, 10))

>>> Y, X = np.mgrid[-3:3:100j, -3:3:100j]

>>> U = -1 - X**2 + Y

>>> V = 1 + X - Y**2

>>> from matplotlib.cbook import get_sample_data

>>> img = np.load(get_sample_data('axes_grid/bivariate_normal.npy'))

>>> lines = ax.plot(x,y) Draw points with lines or markers connecting them

>>> ax.scatter(x,y) Draw unconnected points, scaled or colored

>>> axes[0,0].bar([1,2,3],[3,4,5]) Plot vertical rectangles (constant width)

>>> axes[1,0].barh([0.5,1,2.5],[0,1,2]) Plot horiontal rectangles (constant height)

>>> axes[1,1].axhline(0.45) Draw a horizontal line across axes

>>> axes[0,1].axvline(0.65) Draw a vertical line across axes

>>> ax.fill(x,y,color='blue') Draw filled polygons

>>> ax.fill_between(x,y,color='yellow') Fill between y-values and 0

3 Plotting Routines

1D Data

>>> fig, ax = plt.subplots()

>>> im = ax.imshow(img, Colormapped or RGB arrays cmap='gist_earth', interpolation='nearest',

vmin=-2,

vmax=2)

2D Data or Images

Vector Fields

>>> axes[0,1].arrow(0,0,0.5,0.5) Add an arrow to the axes

>>> axes[1,1].quiver(y,z) Plot a 2D field of arrows

>>> axes[0,1].streamplot(X,Y,U,V) Plot 2D vector fields

Data Distributions

>>> ax1.hist(y) Plot a histogram

>>> ax3.boxplot(y) Make a box and whisker plot

>>> ax3.violinplot(z) Make a violin plot

>>> axes2[0].pcolor(data2) Pseudocolor plot of 2D array

>>> axes2[0].pcolormesh(data) Pseudocolor plot of 2D array

>>> CS = plt.contour(Y,X,U) Plot contours

>>> axes2[2].contourf(data1) Plot filled contours

>>> axes2[2]= ax.clabel(CS) Label a contour plot

Figure

Axes/Subplot

Y-axis

X-axis

1D Data

2D Data or Images

>>> plt.plot(x, x, x, x**2, x, x**3)

>>> ax.plot(x, y, alpha = 0.4)

>>> ax.plot(x, y, c='k')

>>> fig.colorbar(im, orientation='horizontal')

>>> im = ax.imshow(img,

cmap='seismic')

>>> fig, ax = plt.subplots()

>>> ax.scatter(x,y,marker=".")

>>> ax.plot(x,y,marker="o")

>>> plt.title(r'$sigma_i=15$', fontsize=20)

>>> ax.text(1,

-2.1, 'Example Graph', style='italic')

>>> ax.annotate("Sine", xy=(8, 0),

xycoords='data', xytext=(10.5, 0),

textcoords='data', arrowprops=dict(arrowstyle="->", connectionstyle="arc3"),)

>>> plt.plot(x,y,linewidth=4.0)

>>> plt.plot(x,y,ls='solid')

>>> plt.plot(x,y,ls='--')

>>> plt.plot(x,y,'--',x**2,y**2,'-.')

>>> plt.setp(lines,color='r',linewidth=4.0)

>>> import matplotlib.pyplot as plt

Close & Clear

>>> plt.cla() Clear an axis

>>> plt.clf() Clear the entire figure

>>> plt.close() Close a window

Matplotlib’s animation base class deals with the animation part. It provides a framework around which the animation functionality is built. There are two main interfaces to achieve that using:
FuncAnimation makes an animation by repeatedly calling a function func.
ArtistAnimation: Animation using a fixed set of Artist objects.
However, out of the two, FuncAnimation is the most convenient one to use. You can read more about them in the documentation since we will only concern ourselves with the FuncAnimation tool.
Modules including numpy and matplotlib should be installed.
To save the animation on your system as mp4 or gif, ffmpeg or imagemagick is required to be installed.
Once ready, we can begin with our first basic animation in the Jupyter Notebooks. The code for this article can be accessed from the associated Github Repository or you can view it on my binder by clicking the image below.
Let’s use FuncAnimation to create a basic animation of a sine wave moving across the screen. The source code for the animation has been taken from the Matplotlib Animation tutorial. Let’s first see the output and then we shall break down the code to understand what’s going under the hood.
In lines(7–9), we simply create a figure window with a single axis in the figure. Then we create our empty line object which is essentially the one to be modified in the animation. The line object will be populated with data later.
In lines(11–13), we create the init function that will make the animation happen. The init function initializes the data and also sets the axis limits.
In lines(14–18), we finally define the animation function which takes in the frame number(i) as the parameter and creates a sine wave(or any other animation) which a shift depending upon the value of i. This function here returns a tuple of the plot objects which have been modified which tells the animation framework what parts of the plot should be animated.
In line 20, we create the actual animation object. The blit parameter ensures that only those pieces of the plot are re-drawn which have been changed.
This is the basic intuition behind creating animations in Matplotlib. With a little tweak in the code, interesting visualizations can be created. Let’s have a look at some of them
Similarly, there is a nice example of creating shapes at GeeksforGeeks. Let’s now create a moving coil that slowly unwinds, with the help of animation class of matplotlib. The code is quite similar to the sine wave plot with minor adjustments.
Live updating graphs come in handy when plotting dynamic quantities like stock data, sensor data or any other time-dependent data. We plot a base graph which automatically gets updated as more data is fed into the system. This example has been taken from sentdex. Be sure to visit this youtube channel for some awesome tutorials.
Let’s plot stock prices of a hypothetical company in a month.
Now, open the terminal and run the python file. You will get a graph like the one below which automatically updates as follows:
Here interval is 1000 milliseconds or one second.
Creating 3D graphs is common but what if we can animate the angle of view of those graphs. The idea is to change the camera view and then use every resulting image to create an animation. There is a nice section dedicated to it at The Python Graph Gallery.
Create a folder called volcano in the same directory as the notebook. All the images will be stored in this folder which will be then used in the animation.
This will create multiple PNG files in the Volcano folder. Now, use ImageMagick to transform them into animation. Open Terminal and navigate to the Volcano folder and enter the following command:
convert -delay 10 Volcano*.png animated_volcano.gif
Celluloid is a Python module that simplifies the process of creating animations in matplotlib. This library creates a matplotlib figure and creates a Camera from it. It then reuses figure and after each frame is created, take a snapshot with the camera. Finally, an animation is created with all the captured frames.
pip install celluloid
Here are a few examples using the Celluloid module.
Animations help to highlight certain features of the visualisation which otherwise cannot be communicated easily with static charts. Having said that it is also important to keep in mind that unnecessary and overuse of visualisations can sometimes complicate things. Every feature in data visualisation should be used judiciously to have the best impact.