Advanced plots in Matplotlib - Part 2


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.

Read the Advanced plots in Matplotlib — Part 1 here.


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() 

Event/Spike Raster plot in Matplotlib

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()
Timelines of the Android Version history in Matplotlib

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()
    
Default style in matplotlib

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()
Classic Style

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()
    
ggplot style

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()
FiveThirtyEight style

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()
bmh style

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()
CyberPunk Style

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.

L: before ; R:After

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.

Categories: Data Visualisation, PythonTags: , , ,

1 comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: