Learn how to customize PyLab using style in this article by Benjamin Walter Keller, a PhD candidate at McMaster University with BSc in physics with a minor in computer science from the University of Calgary in 2011.
This article will delve into advanced Matplotlib plots so that you can really derive more subtle insights from your data.
Customizing PyLab using style
Start by importing numpy, matplotlib, and pyplot as follows:
1 2 3 |
import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt |
Also import matplotlib and a couple of extra lines to make our plots show up in a proper format:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
%matplotlib inline # Set up figure size and DPI for screen demo plt.rcParams['figure.figsize'] = (6,4) plt.rcParams['figure.dpi'] = 150 from scipy.ndimage.filters import gaussian_filter plt.subplot(221) plt.text(0.5, 0.5, 'hello') plt.plot(np.arange(0,1,0.01), np.power(np.arange(0,1,0.01), 3)) plt.ylabel('Axis Label') plt.subplot(222) plt.scatter(np.random.normal(size=10), np.random.normal(size=10), c=np.random.normal(size=10)) plt.subplot(223) plt.hist(np.random.normal(size=1000)); plt.hist(np.random.normal(1, size=1000)); plt.hist(np.random.normal(2, size=500)); plt.ylabel('Axis Label') plt.xlabel('Axis Label') plt.subplot(224) plt.imshow(gaussian_filter(np.random.normal(size=(200,300)), sigma=10)) plt.xlabel('Axis Label') |
Begin with the preceding big block of code and make an array—a little grid of four plots showing four basic plot types which includes a line plot (top left), a scatter plot (top right), a histogram (bottom left), and an image plot (bottom right), along with the respective axis labels:
By default, Matplotlib will choose some fairly sensible choices for things like fonts, colors, and the other appearance attributes of these plots. These defaults aren’t the only choices for appearance attributes that Matplotlib provides.
How to use styles to change the appearance of our plots
Using the style module within pyplot, you can see that when we call the function available, we actually get a list containing a number of different styles. Let’s assume that each of these different styles acts to change the attributes and the appearance of the plots:
So, by using the plot.style.use method, we can load up any one of these default style sheets. Using the ggplot (as shown in the preceding output) will actually mimic the appearance of the ggplot library, as you can see in the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# Using styles plt.style.use('dark_background') from scipy.ndimage.filters import gaussian_filter plt.subplot(221) plt.plot(np.arange(0,1,0.01), np.power(np.arange(0,1,0.01), 3)) plt.ylabel('Axis Label') plt.subplot(222) plt.scatter(np.random.normal(size=10), np.random.normal(size=10), c=np.random.normal(size=10)) plt.subplot(223) plt.hist(np.random.normal(size=1000)); plt.hist(np.random.normal(1, size=1000)); plt.hist(np.random.normal(2, size=500)); plt.ylabel('Axis Label') plt.xlabel('Axis Label') plt.subplot(224) plt.imshow(gaussian_filter(np.random.normal(size=(200,300)), sigma=10)) plt.xlabel('Axis Label') |
After calling the plt.style.use('ggplot') method, we have the same kind of plots shown, but the axis objects and the appearance of these has been changed fairly significantly. There exists a white grid on a gray background, the fonts have changed as well as their colors, and the default color choices have changed as well.
Hence, we see that the histogram will have different colors, as shown in the following output:
We can also change this to any other choice as well. If you’re familiar with the Seaborn library, a Python library for doing more complicated analysis statistically, you can choose options that will mimic the Seaborn library:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# Using styles plt.style.use('seaborn-talk') from scipy.ndimage.filters import gaussian_filter plt.subplot(221) plt.plot(np.arange(0,1,0.01), np.power(np.arange(0,1,0.01), 3)) plt.ylabel('Axis Label') plt.subplot(222) plt.scatter(np.random.normal(size=10), np.random.normal(size=10), c=np.random.normal(size=10)) plt.subplot(223) plt.hist(np.random.normal(size=1000)); plt.hist(np.random.normal(1, size=1000)); plt.hist(np.random.normal(2, size=500)); plt.ylabel('Axis Label') plt.xlabel('Axis Label') plt.subplot(224) plt.imshow(gaussian_filter(np.random.normal(size=(200,300)), sigma=10)) plt.xlabel('Axis Label') |
Different Matplotlib styles
In this section, we will be learning about various styles provided by Matplotlib such as temporary styles or creating your own custom styles. The following are a few examples of different styles:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# Temporary styles plt.style.use('classic') from scipy.ndimage.filters import gaussian_filter plt.subplot(221) plt.plot(np.arange(0,1,0.01), np.power(np.arange(0,1,0.01), 3)) plt.ylabel('Axis Label') plt.subplot(222) with plt.style.context('ggplot'): plt.scatter(np.random.normal(size=10), np.random.normal(size=10), c=np.random.normal(size=10)) plt.subplot(223) plt.hist(np.random.normal(size=1000)); plt.hist(np.random.normal(1, size=1000)); plt.hist(np.random.normal(2, size=500)); plt.ylabel('Axis Label') plt.xlabel('Axis Label') plt.subplot(224) plt.imshow(gaussian_filter(np.random.normal(size=(200,300)), sigma=10)) plt.xlabel('Axis Label') |
Using the dark background will give you an image that shows up nicely on a dark background; hence if you’re building slides, you might want to use the dark background style sheet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# Custom styles plt.style.use('bigpoints') from scipy.ndimage.filters import gaussian_filter plt.subplot(221) plt.plot(np.arange(0,1,0.01), np.power(np.arange(0,1,0.01), 3), 'ko') plt.ylabel('Axis Label') plt.subplot(222) plt.scatter(np.random.normal(size=10), np.random.normal(size=10), c=np.random.normal(size=10)) plt.subplot(223) plt.hist(np.random.normal(size=1000)); plt.hist(np.random.normal(1, size=1000)); plt.hist(np.random.normal(2, size=500)); plt.ylabel('Axis Label') plt.xlabel('Axis Label') plt.subplot(224) plt.imshow(gaussian_filter(np.random.normal(size=(200,300)), sigma=10)) plt.xlabel('Axis Label') |
(Note from vitoshacademy.com – it will not produce the output below, but an error message for missing custom style – “Big Points”. To avoid the error message, make sure to create the custom style “Big Points”, as instructed later in the article)
You will see the output, which shows the black background:
You can also choose style sheets temporarily. So, previously, we have chosen a style sheet that affects all four plots. If, for example, I take my scatter plot and put it with a plt.style.context block and choose a style sheet, let’s say ggplot , you can see that we have actually overridden it, as shown here:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# Temporary styles plt.style.use('classic') from scipy.ndimage.filters import gaussian_filter plt.subplot(221) plt.plot(np.arange(0,1,0.01), np.power(np.arange(0,1,0.01), 3)) plt.ylabel('Axis Label') plt.subplot(222) with plt.style.context('ggplot'): plt.scatter(np.random.normal(size=10), np.random.normal(size=10), c=np.random.normal(size=10)) plt.subplot(223) plt.hist(np.random.normal(size=1000)); plt.hist(np.random.normal(1, size=1000)); plt.hist(np.random.normal(2, size=500)); plt.ylabel('Axis Label') plt.xlabel('Axis Label') plt.subplot(224) plt.imshow(gaussian_filter(np.random.normal(size=(200,300)), sigma=10)) plt.xlabel('Axis Label') |
From the preceding code, we can see there’s a small difference, but the color map has changed:
So, this one scatter plot has temporarily used a different set of choices for the appearance compared to the previous ones, so the other panels here are using the classic style sheet, whereas this is using ggplot, which changes the attributes of these points.
Creating your own styles
A question arises, can we actually make our own style sheet? The answer to that, of course, is yes. The first thing you need to know is where to put these style sheets.
So, when we run mpl.get_configdir, you can see we get a directory where the Matplotlib configuration options are stored and here we can actually place new style sheets:
1 2 |
# Where do we put out style sheets? mpl.get_configdir() |
We will thus generate our simple plot again by using a classic style sheet. Let’s build a new style sheet; we will build something simple that will change just a single attribute. To build a new style sheet, we will follow these steps:
- We will make a directory called stylelib —this will be where style files are actually stored, and these style sheets will live in this stylelib directory:
1 2 3 |
$ ls $ mkdir stylelib $ cd stylelib |
- We will make one style sheet and name it bigpoints.mplstyle . .mplstyleis the file name extension for Matplotlib style sheets.
- Insert the marker size and make it 20:
1 |
lines.markersize: 20 |
- We will restart the kernel by clicking on the Kernel tab and then on Restart since we have created this new style sheet that only gets loaded in when Matplotlib is actually started up, as shown in the following screenshot:
- By going back to the Jupyter Notebook, we will reimport the following packages:
1 2 3 4 5 6 7 8 |
import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt %matplotlib inline # Set up figure size and DPI for screen demo plt.rcParams['figure.figsize'] = (6,4) plt.rcParams['figure.dpi'] = 150 |
- Next, we call style.availableand we see the addition to all of the big points, as shown in the following output:
- By running style.use('bigpoints'), we can see it’s changed the size of the points, as shown here:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# Custom styles plt.style.use('bigpoints') from scipy.ndimage.filters import gaussian_filter plt.subplot(221) plt.plot(np.arange(0,1,0.01), np.power(np.arange(0,1,0.01), 3)) plt.ylabel('Axis Label') plt.subplot(222) with plt.style.context('ggplot'): plt.scatter(np.random.normal(size=10), np.random.normal(size=10), c=np.random.normal(size=10)) plt.subplot(223) plt.hist(np.random.normal(size=1000)); plt.hist(np.random.normal(1, size=1000)); plt.hist(np.random.normal(2, size=500)); plt.ylabel('Axis Label') plt.xlabel('Axis Label') plt.subplot(224) plt.imshow(gaussian_filter(np.random.normal(size=(200,300)), sigma=10)) plt.xlabel('Axis Label') |
We will get the following output:
- So, by typing ko, we get black dots. In the following image, you can see that those are quite big:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# Custom styles plt.style.use('bigpoints') from scipy.ndimage.filters import gaussian_filter plt.subplot(221) plt.plot(np.arange(0,1,0.01), np.power(np.arange(0,1,0.01), 3), 'ko') plt.ylabel('Axis Label') plt.subplot(222) plt.scatter(np.random.normal(size=10), np.random.normal(size=10), c=np.random.normal(size=10)) plt.subplot(223) plt.hist(np.random.normal(size=1000)); plt.hist(np.random.normal(1, size=1000)); plt.hist(np.random.normal(2, size=500)); plt.ylabel('Axis Label') plt.xlabel('Axis Label') plt.subplot(224) plt.imshow(gaussian_filter(np.random.normal(size=(200,300)), sigma=10)) plt.xlabel('Axis Label') |
From the preceding code, we get the following output:
- We will go back and edit this and insert 50points (more than twice what was shown earlier):
1 |
lines.markersize: 50 |
- After reimporting matplotlib , run plt.style.use('bigpoints') using a new style sheet; we can see that the points are bigger than they were before.
Styles can also be composed using two sets of styles, so you can combine the attributes of two different style sheets to generate things that have different combinations, and the way to do that is actually to use a list for plt.style.use.
By typing ggplot and composing that with dark_background , all of the subsequent changes that the dark background provides overwrites the changes that ggplot provides:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# Composing styles plt.style.use(['ggplot', 'dark background']) from scipy.ndimage.filters import gaussian_filter plt.subplot(221) plt.plot(np.arange(0,1,0.01), np.power(np.arange(0,1,0.01), 3), 'ko') plt.ylabel('Axis Label') plt.subplot(222) plt.scatter(np.random.normal(size=10), np.random.normal(size=10), c=np.random.normal(size=10)) plt.subplot(223) plt.hist(np.random.normal(size=1000)); plt.hist(np.random.normal(1, size=1000)); plt.hist(np.random.normal(2, size=500)); plt.ylabel('Axis Label') plt.xlabel('Axis Label') plt.subplot(224) plt.imshow(gaussian_filter(np.random.normal(size=(200,300)), sigma=10)) plt.xlabel('Axis Label') |
We will get the following output:
So, in other words, what we have here is a combination of ggplot modules and dark background changes, hence all of the things that ggplot changes, the dark background does not. All of the changes that both ggplot and the dark background change use the changes from the dark background, and all of the changes that ggplot does not make but the dark background does get applied.
It’s kind of like an overwrite, wherein the dark background is applied after ggplot is applied. You can make custom style sheets and then compose them so that each style sheet can work together. So, for example, you can have a style sheet that will change line attributes that you can then compose with a style sheet that will change the axis or label attribute, and you can use that to modify the built-in default Matplotlib style sheets.
Taking an example, if you really loved the look of ggplot but you didn’t quite like one little attribute of it, you could actually go in and change that, as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# Composing styles plt.style.use(['ggplot']) from scipy.ndimage.filters import gaussian_filter plt.subplot(221) plt.plot(np.arange(0,1,0.01), np.power(np.arange(0,1,0.01), 3)) plt.ylabel('Axis Label') plt.subplot(222) plt.scatter(np.random.normal(size=10), np.random.normal(size=10), c=np.random.normal(size=10)) plt.subplot(223) plt.hist(np.random.normal(size=1000)); plt.hist(np.random.normal(1, size=1000)); plt.hist(np.random.normal(2, size=500)); plt.ylabel('Axis Label') plt.xlabel('Axis Label') plt.subplot(224) plt.imshow(gaussian_filter(np.random.normal(size=(200,300)), sigma=10)) plt.xlabel('Axis Label') |
If you want to turn off these grid labels, you can create a new style sheet, disable grid labels, compose that with the ggplot style sheet, and get a plot that looks exactly the same but without those white grid lines, as follows: