This article comes as a second part in the Advanced Plots in Matplotlib series. In Part 1, we learnt how to use plots like Span selector, Broken Horizontal Bar plot and the table function in our visualisation work. We also learnt how to watermark images and add a twist to the plots in Matplotlib by using the XKCD theme. In part 2, we shall go over some of the other interesting capabilities of Matplotlib in action and use it to jazz up our existing plots.
1. Event Plots
Event plots come in handy when one wants to plot identical parallel lines at pre-defined positions. Such plots are commonly used in neuroscience to display the spiking activity of the neurons over time, where it is frequently referred to as a spike raster or simply a raster plot. However, there are other uses for such kind of plots too. Here is an excerpt from the event plot documentation :
It is useful in any situation where you wish to show the timing or position of multiple sets of discrete events, such as the arrival times of people to a business on each day of the month or the date of hurricanes each year of the last century.
Let’s look at an eventplot
showing sequences of events with various line properties. The plot is shown in both horizontal and vertical orientations. The plot has been adapted from official Matplotlib’s Eventplot documentation.
import matplotlib.pyplot as plt
import numpy as np
# Creating rows of random data with 50 data points
data = np.random.random([8, 50])
colorsCodes = ['C{}'.format(i) for i in range(8)]
# Set spike colors for each neuron
lineSize = [.2, 0.3, 0.2, 0.8, 0.5, 0.6, 0.7, 0.9]
fig, ax = plt.subplots(1, 2)
# Creating a horizontal plot
ax[0].eventplot(data, color=colorsCodes, linelengths = lineSize)
ax[0].set_title('Spike Raster plot- Horizontal')
ax[0].set(xlabel="Spike",ylabel="Neuron")
ax[1].eventplot(data, color=colorsCodes, linelengths = lineSize, orientation='Vertical')
ax[1].set_title('Spike Raster plot- Vertical')
ax[1].set(ylabel="Spike",xlabel="Neuron")
plt.tight_layout()
plt.savefig('event.png')
plt.show()

2. Timelines
Did you know that it is possible to create a simple timeline using Matplotlib alone? Well yes. This is because technically, timelines are simply collections of dates and text which can be obtained with simple variations in a stem plot. You can read more about it here.
Here is a timeline showing the Android version history using the code provided in the official documentation.
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.dates as mdates
from datetime import datetime
names = ['Gingerbread', 'Ice Cream Sandwich', 'Jelly Bean', 'KitKat', 'Lollipop', 'Marshmallow',
'Nougat', 'Oreo', 'Pie', '10', '11']
dates = ['2011-02-9', '2011-10-19', '2012-11-13', '2013-10-31',
'2014-11-3', '2015-10-5', '2016-08-22', '2017-08-21',
'2018-08-06', '2019-09-3', '2020-02-19']
# Convert date strings (e.g. 2014-10-18) to datetime
dates = [datetime.strptime(d, "%Y-%m-%d") for d in dates]
# Choose some nice levels
levels = np.tile([-5, 5, -3, 3, -1, 1],
int(np.ceil(len(dates)/6)))[:len(dates)]
# Create figure and plot a stem plot with the date
fig, ax = plt.subplots(figsize=(8.8, 4), constrained_layout=True)
ax.set(title="Android version history")
markerline, stemline, baseline = ax.stem(dates, levels,
linefmt="C3-", basefmt="k-",
use_line_collection=True)
plt.setp(markerline, mec="k", mfc="w", zorder=3)
# Shift the markers to the baseline by replacing the y-data by zeros.
markerline.set_ydata(np.zeros(len(dates)))
# annotate lines
vert = np.array(['top', 'bottom'])[(levels > 0).astype(int)]
for d, l, r, va in zip(dates, levels, names, vert):
ax.annotate(r, xy=(d, l), xytext=(-3, np.sign(l)*3),
textcoords="offset points", va=va, ha="right")
# format xaxis with 10 month intervals
ax.get_xaxis().set_major_locator(mdates.MonthLocator(interval=10))
ax.get_xaxis().set_major_formatter(mdates.DateFormatter("%b %Y"))
plt.setp(ax.get_xticklabels(), rotation=30, ha="right")
# remove y axis and spines
ax.get_yaxis().set_visible(False)
for spine in ["left", "top", "right"]:
ax.spines[spine].set_visible(False)
ax.margins(y=0.1)
plt.show()

3. Bar of Pie
Have you ever wanted to further drill down into a pie chart? Maybe you wanted to expand one of its slices and ‘explode’ it into a bar chart? Matplotlib makes it possible through a ‘Bar of Pie’ functionality. It uses a ConnectionPatch that connects two points (possibly in different axes).
The idea is simple. Create a pie chart and its corresponding bar chart as subplots and then use a connection patch to draw lines between the two subplots.
Here is an example from the official documentation.
4. Style sheets reference
While creating plots in matplotlib, a lot of times, we tend to stick with the default style. However, Matplotlib offers a bunch of great style options which make even the mundane visualisations really stand out. To list all of the styles, enter the following line of code.
print(plt.style.available)
Output: ['Solarize_Light2', '_classic_test_patch', 'bmh', 'classic', 'dark_background', 'fast', 'fivethirtyeight', 'ggplot', 'grayscale', 'seaborn', 'seaborn-bright', 'seaborn-colorblind', 'seaborn-dark', 'seaborn-dark-palette', 'seaborn-darkgrid', 'seaborn-deep', 'seaborn-muted', 'seaborn-notebook', 'seaborn-paper', 'seaborn-pastel', 'seaborn-poster', 'seaborn-talk', 'seaborn-ticks', 'seaborn-white', 'seaborn-whitegrid', 'tableau-colorblind10']
Here I’ll showcase some of the popular ones. In case you are interested, you can find the complete list here. Let’s create a basic line plot and then apply some of the different styles. When no style has been specified, matplotlib will use the default style:
import matplotlib.pyplot as plt
plt.plot([1, 3, 9, 5, 2, 1, 1], marker='o')
plt.plot([4, 5, 5, 7, 9, 8, 6], marker='v')
plt.plot([2, 3, 4, 3, 4, 5, 3], marker='s')
plt.show()

To add a style of your choice, insert the following line in your code:
plt.style.use('stylename') #Replace 'stylename' with the desired style
Commonly used styles:
Let’s see some of the commonly used styles:
Classic
Classic is Matplotlib’s older style.
import matplotlib.pyplot as plt
plt.style.use("classic")
plt.plot([1, 3, 9, 5, 2, 1, 1], marker='o')
plt.plot([4, 5, 5, 7, 9, 8, 6], marker='v')
plt.plot([2, 3, 4, 3, 4, 5, 3], marker='s')
plt.show()

ggplot
This style emulates the aesthetics of ggplot (a popular plotting package for R)
import matplotlib.pyplot as plt
plt.style.use("ggplot")
plt.plot([1, 3, 9, 5, 2, 1, 1], marker='o')
plt.plot([4, 5, 5, 7, 9, 8, 6], marker='v')
plt.plot([2, 3, 4, 3, 4, 5, 3], marker='s')
plt.show()

FiveThirtyEight
This shows an example of the “fivethirtyeight” styling, which tries to replicate the styles from fivethirtyeight.com.
import matplotlib.pyplot as plt
plt.style.use("fivethirtyeight")
plt.plot([1, 3, 9, 5, 2, 1, 1], marker='o')
plt.plot([4, 5, 5, 7, 9, 8, 6], marker='v')
plt.plot([2, 3, 4, 3, 4, 5, 3], marker='s')
plt.show()

Bayesian Methods for Hackers — bmh
This example demonstrates the style used in the Bayesian Methods for Hackers online book.
import matplotlib.pyplot as plt
plt.style.use("bmh")
plt.plot([1, 3, 9, 5, 2, 1, 1], marker='o')
plt.plot([4, 5, 5, 7, 9, 8, 6], marker='v')
plt.plot([2, 3, 4, 3, 4, 5, 3], marker='s')
plt.show()

Cyberpunk style
Recently, I stumbled upon a package named mplcyberpunk, which is a Python package on top of matplotlib
to create ‘cyberpunk’ style plots with just three additional lines of code. How cool is that 🤘?
To use the cyberpunk style; you will need to install and import the library first.
!pip install mplcyberpunk
import matplotlib.pyplot as plt
import mplcyberpunk
plt.style.use("cyberpunk")
plt.plot([1, 3, 9, 5, 2, 1, 1], marker='o')
plt.plot([4, 5, 5, 7, 9, 8, 6], marker='v')
plt.plot([2, 3, 4, 3, 4, 5, 3], marker='s')
# Add glow effects-Optional
mplcyberpunk.add_glow_effects()
plt.show()

5. adjustText — automatic label placement for matplotlib
Lastly, let’s look at a useful Third-party package in Matplotlib. As the name suggests, third party packages build and extend the existing Matplotlib capabilities. An important point to keep in mind is that these packages are not included in Matplotlib by default and have to be installed separately.
adjustText
A lot of times, we struggle to adjust the text positions in a graph. This happens when there are multiple labels, and these labels start overlapping. adjustText is a pretty useful library for such situations as it automates the placement of labels.
Installation
As already stated, you’ll need to install the library first, which can be done by either of the three ways:
pip install adjustText # pip install or conda install -c conda-forge adjusttext # conda or # For the latest version from GitHub: pip install https://github.com/Phlya/adjustText/archive/master.zip
Usage
Let’s look at a basic example from adjustText‘s documentation itself to highlight the power of adjustText. The figures on the left shows the overlapping labels while the figure on the right shows the auto adjusted labels obtained after calling the adjust_text
function.


Wrap Up
This brings us to the end of our two-part series on advanced Matplotlib plots. In this series, we saw some of the interesting capabilities of matplotlib, which could be really useful in making a compelling storyline. To conclude, let’s look at an interesting visualisation that I found on the Matplolib blog site.
You must have guessed it. It is the animated version of the Tesla Cybertruck It has been created purely using Matplotlib. The visualisation is a result of the interaction between the Figure, Axes and the object-oriented interface of Matplotlib. Hop over to the code to create something similar of your own and share it with the world.
One thought on “Advanced plots in Matplotlib - Part 2”