Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Mastering Matplotlib 2.x
Mastering Matplotlib 2.x

Mastering Matplotlib 2.x: Effective Data Visualization techniques with Python

By Benjamin Walter Keller
$32.99
Book Nov 2018 214 pages 1st Edition
eBook
$25.99 $17.99
Print
$32.99
Subscription
$15.99 Monthly
eBook
$25.99 $17.99
Print
$32.99
Subscription
$15.99 Monthly

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Black & white paperback book shipped to your address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Buy Now

Product Details


Publication date : Nov 29, 2018
Length 214 pages
Edition : 1st Edition
Language : English
ISBN-13 : 9781789617696
Category :
Table of content icon View table of contents Preview book icon Preview Book

Mastering Matplotlib 2.x

Heavy Customization

This book will teach us about advanced Matplotlib plots. It will enable you to go from data to plot to insight, in order to take raw numbers, raw information, and turn them into a visualization, which will allow us to build within our mind the actual bit of insight on how the data behaves. This will also focus on the advanced tools to derive more subtle insights from your data.

In this chapter, we will be focusing on the advanced tools of plotting so that you can really derive more subtle insights from your data. The prerequisites for this course give us a basic understanding of Python and the ability to use NumPy to work with array data.

We will learn about the following topics:

  • Using style sheets to customize our plot's appearance
  • Working with Matplotlib colors
  • Building multi-panel plots with complex layouts
  • How to configure Matplotlib to use our preferences whenever we start up a new Matplotlib session

Customizing PyLab using style

We will start by importing numpy, matplotlib, and pyplot, as follows:

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

We will also import matplotlib and also import a couple of extra lines to make our plots show up in a proper format:

%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')

We will begin with the preceding big block of code and will 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

By 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:

# 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:

# 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:

# 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:

# 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')

You will see the output, which shows the black background:

You can also choose style sheets temporarily. So, previously, we have chose a style sheet that affects all four plots. If, for example, I take my scatter plot and put it in a with 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:

# 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:

# 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:

  1. 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:
$ ls
$ mkdir stylelib
$ cd stylelib
  1. We will make one style sheet and name it bigpoints.mplstyle.
.mplstyle is the file name extension for Matplotlib style sheets.
  1. Insert the marker size and make it 20:
lines.markersize: 20
  1. 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:
  1. By going back to the Jupyter Notebook, we will reimport the following packages:
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
  1. Next, we call plt.style.available and we see the addition to all of the big points, as shown in the following output:
  1. By running plt.style.use('bigpoints'), we can see it's changed the size of the points, as shown here:
# 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:

  1. So, by typing ko, we get black dots. In the following image after the code snippet, you can see that those are quite big:
# 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:

  1. We will go back and edit this and insert 50 points (more than twice what was shown earlier):
lines.markersize: 50
  1. 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:

# 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:

# 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:

In the next section, we are going to take a deep dive into looking at colors within Matplotlib and how to configure and customize them.

Deep diving into color

When it comes to choosing color maps, we have a near infinite set of choices available to us, so it makes a lot of sense to think about the theory of why certain color maps are designed in the way they are.

A classic paper on the theory of Choosing a Colour Sequence for Univariate Maps was published by Colin Ware over 30 years ago. In this paper, Dr. Ware defines two different important things to think about when choosing a color map:

  • How a color map conveys the metric value of individual points within the image
  • How that color map conveys form—the shape of the different points interacting within each other

Questions to ask when choosing a color map

Different color maps can perform better or worse at conveying metrics, letting the viewer know the value of pixels on the screen, and conveying form—showing how those pixels relate to one another. Whether or not form or metrics or both are important for a given image is really key to deciding what kind of color map to use for that image.

The different questions that can be asked when choosing a color map are as follows:

  • Do we need to think whether or not the shape, the value, or-again-both are important for that field?
  • Are there critical values or transitions in the data?
  • Are there ranges of numbers that really want to pop out to the viewer?
  • What is the intuitive choice of colors for the dataset?

For most people, a dataset that conveys temperature should usually have hot red colors to denote high temperatures and cool blue colors to denote cold temperatures; to reverse that would violate the intuitive sense that the viewer has and set up an initial set of stressors in their mind that's going to make interpreting the image harder than it needs to be.

Taking an example, have a look at the color map here, showing population density in the United States:

Using one kind of color map—one that's not perceptually uniform—washes out a lot of the high values. Simply changing it to another different kind of color map that has less high-valued whitish colors at the high end allows you to see more detail in the higher density, more populated eastern parts of the US.

To take a look at all of the color maps that Matplotlib provides, visit the website provided here: http://matplotlib.org/examples/color/colormaps_reference.html. This offers a little swatch of each different color map to give you an idea of what the color map can do in terms of the ranges.

Before we move ahead with the code, we will start by importing the following set of default packages, as shown here:

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

Using color maps

Now, we can choose a color map from Matplotlib's selection of color maps by passing the cmap='inferno' color map:

from scipy.ndimage.filters import gaussian_filter
plt.imshow(gaussian_filter(np.random.normal(size=(200,300)), sigma=10))

The following displays the image using the inferno color map:

We can see the differences in the value between dark cool colors and white hot colors. The perceptually uniform color maps are good at conveying both metric and form. There are color maps that you might want to choose for different kinds of purposes.

For example, the seismic color map, which is one of the diverging color maps, is very good for showing differences between the middle values of your plot. So, divergences towards the highly positive or highly negative in most of the values near the median of the pixels are hard to distinguish. What instead pops out to the viewer are the highly positive and highly negative ranges, as shown in the following code and image:

from scipy.ndimage.filters import gaussian_filter
plt.imshow(gaussian_filter(np.random.normal(size=(200,300)), sigma=10), cmap='seismic')

The following is the output of the preceding code:

Another option is one of the miscellaneous color maps, flag. This is a really good example of a color map that maximizes the amount of information available in terms of the form that is the shape of the data, but completely loses any metric information. This color map actually cycles, so there are multiple different values corresponding to red, white, black, and blue. In a way, it gives you a set of contours much like the contour command does:

# Choose a new colormap
from scipy.ndimage.filters import gaussian_filter
plt.imshow(gaussian_filter(np.random.normal(size=(200,300)), sigma=10), cmap='flag')

The following is the output of the preceding code:

We can create our own color maps using Matplotlib's colors module. We can create a color map using the listed method from colors that will create a color map from a list of named colors available for our image. So, it will actually create something that looks a lot like a filled contour plot:

# Generate a custom discrete colormap w/ ListedColormap
from matplotlib import colors
from scipy.ndimage.filters import gaussian_filter
plt.imshow(gaussian_filter(np.random.normal(size=(200,300)), sigma=10), cmap=colors.ListedColormap(['r', 'b', 'g']))
plt.colorbar()

Hence, from the preceding code, we get the output contour map showing that the colors are split into three separate pieces. The following plot shows a discrete color map, again, something that's very good for showing form but not particularly good for showing metrics unless we had to include a large range of colors that would split this up and make it more continuous:

Now, this linear segmented color map requires a call structure, which is a basic ListedColor.

We will include the first argument as my_map as we are creating a new one, which also requires a dictionary as its second argument, called cdict:

# Generate a custom discrete colormap w/ LinearSegmentedColormap
cdict = dict(red=[(0, 0, 0.5), (0.5, 1, 0.5), (1, 1, 0.5)],
green=[(0,0,1), (1, 0, 1)],
blue=[(0, 0, 1), (1, 0, 1)])
plt.imshow(gaussian_filter(np.random.normal(size=(200,300)), sigma=10), cmap=colors.LinearSegmentedColormap('my_map',cdict))
plt.colorbar()

In the preceding code, we can see that there are three keyword arguments: red, green, and blue. Each of these is itself a list and these lists have elements that are three-element tuples; these tuples can be seen for the initial and last elements for the colors red, green, and blue.

Each of the three numbers in this tuple corresponds to the start value of that segment, the amount of that color we get in that value of the segment, and the alpha or transparency of that value in the segment. In the preceding plot, the color red becomes fully saturated at the end of our color map. The color red contains an extra element in the middle when we reach full saturation, as shown in the following colored map:

Adding a bit of opacity that allows between 0 and 0.5, as shown in the preceding code snippet, we get the following output:

The previous output shows a linear segmented color map which is a way to create any kind of complex sophisticated color map.

Let's look at another example, where colors are important in Matplotlib. We have seen already that the Matplotlib backend will automatically cycle through colors, so you can see in the next output that there are different waveforms:

To reset and interchange the colors, the axis object we learned has a set_prop_cycle argument. That cycler decides what the next color should be, so if we set the prop cycle to None after every second set of plot commands, we can see that the cycle changes the color and loops again, as follows:

# Color cycler: reset with Axes set_prop_cycle(None) method
nums = np.arange(0,10,0.1)
plt.plot(nums, np.sin(nums), label='1')
plt.plot(1+nums, np.sin(nums), label='2')
plt.gca().set_prop_cycle(None)
plt.plot(2+nums, np.sin(nums), label='3')
plt.plot(3+nums, np.sin(nums), label='4')
plt.gca().set_prop_cycle(None)
plt.plot(4+nums, np.sin(nums), label='5')
plt.legend(loc='best')

We will get the following output:

We reset and go back to the beginning, but not only can we set this to None to reset our cycler, we can use the cycler module that Matplotlib provides. It's actually its own module, so we will import the cycler from itself and not from Matplotlib. By setting the prop cycle to the new color cycler, we can actually define our own cycler.

We have created a cycler that goes from red to blue. We will include another one here, which is cyan, hence we should go from red to cyan to blue and then loop over those again, as seen in the following code:

# Color cycler: custom with cycler
from cycler import cycler
color_cyc = cycler('color', ['red', 'cyan', 'blue'])
plt.gca().set_prop_cycle(color_cyc)
nums = np.arange(0,10,0.1)
plt.plot(nums, np.sin(nums), label='1')
plt.plot(1+nums, np.sin(nums), label='2')
plt.plot(2+nums, np.sin(nums), label='3')
plt.plot(3+nums, np.sin(nums), label='4')
plt.plot(4+nums, np.sin(nums), label='5')
plt.legend(loc='best')

Hence, here, we get the following output:

This is a way of setting up your own set of color cycles, so, for example, if there are lines that have relationships to each other—so say you want to go throughout the red-orange-yellow-green-blue-indigo-violet spectrum with regards to your lines rather than the built-in cycle that Matplotlib provides—you can use this cycler to do it.

Working on non-trivial layouts

We will begin by looking at a subplot with one set of rows and three columns, as shown here:

# Standard Subplot
plt.subplot(131)
plt.subplot(132)
plt.subplot(133)

The following is the output of the preceding input:

Now, by default, it will provide three plots side by side of equal size, but if we want them on top of each other instead, we will choose three rows and one column:

# Standard Subplot
plt.subplot(311)
plt.subplot(312)
plt.subplot(313)

We will get the following output:

But what if these plots aren't necessarily supposed to show three identical ranges? In that case, we have the subplot2grid method:

# subplot2grid 
plt.subplot2grid((2,2), (0,0))
plt.subplot2grid((2,2), (1,0))
plt.subplot2grid((2,2), (0,1))

We will begin by making the same vertical plot as shown previously. Now, specify one row and three columns and in the second tuple, select the rows, because there's only one and three columns. Next, we will see that there's a grid with two rows and three columns. We will place everything in the first column within the first row and simply specify a column:

# subplot2grid 
plt.subplot2grid((2,3), (0,0))
plt.subplot2grid((2,3), (0,1))
plt.subplot2grid((2,3), (0,2))

The output will be as follows:

Now, to get this in a 2 x 3 grid, we need to have two plots underneath a third one; well in that case, what we want is a 2 x 2 grid, so one plot is going to be twice as wide and then two plots beneath, as shown here:

# Adjusting GridSpec attributes: w/h space
gs = mpl.gridspec.GridSpec(2,2)
plt.subplot(gs[0,0])
plt.subplot(gs[1,0])
plt.subplot(gs[1,1])

We will get the following output:

We have the positions right, but this has not actually made the plots bigger. To do that, we will have to pass an argument to the first one, plt.subplot2grid, called colspan=2, and using colspan, we say that this plot should span as shown in the following code:

# subplot2grid 
plt.subplot2grid((2,2), (0,0), colspan=2)
plt.subplot2grid((2,2), (1,0))
plt.subplot2grid((2,2), (0,1))

We will get the following output::

There is also another option as well for doing similar things, but in the vertical direction with row span. Therefore, we can perform the following action:

# subplot2grid 
plt.subplot2grid((2,2), (0,0))
plt.subplot2grid((2,2), (1,0))
plt.subplot2grid((2,2), (0,1), rowspan=2)

From the preceding code, we will get the following output:

We can do the same thing using a GridSpec object and in fact we can customize this a little more explicitly. After creating a GridSpec object, iterate it through the indices of that GridSpec to say where it will get placed. These indices are just like any two-dimensional NumPy array. So, for example, we can perform the following:

# Explicit GridSpec
gs = mpl.gridspec.GridSpec(2,2)
plt.subplot(gs[0,0])
plt.subplot(gs[0,1])

The following is the output of the preceding code:

By including a diagonal pair of plots, we get the following:

# Explicit GridSpec
gs = mpl.gridspec.GridSpec(2,2)
plt.subplot(gs[0,0])
plt.subplot(gs[1,1])

We will get the following output:

We can also make those plots span things using the range syntax that NumPy provides for us:

# Explicit GridSpec
gs = mpl.gridspec.GridSpec(2,2)
plt.subplot(gs[0,:])
plt.subplot(gs[1,1])

The preceding code gives the following output:

If, for example, we made this have three columns, we would get the following:

# Explicit GridSpec
gs = mpl.gridspec.GridSpec(2,3)
plt.subplot(gs[0,:])
plt.subplot(gs[1,1])

We will get the following output:

This shows that we can really dive into providing whatever kind of grid-like layout we want with plots of different sizes and shapes. You can also customize the amount of space between these plots. For example, look at the following grid:

We can adjust the amount of space between the grids using wspace for space between the plots:

# Adjusting GridSpec attributes: w/h space
gs = mpl.gridspec.GridSpec(2,2, wspace=0.5)
plt.subplot(gs[0,0])
plt.subplot(gs[0,1])
plt.subplot(gs[1,0])
plt.subplot(gs[1,1])

The preceding code gives the following output:

We can also adjust the amount of space between the grids using hspace for space between the plots:

# Adjusting GridSpec attributes: w/h space
gs = mpl.gridspec.GridSpec(2,2, hspace=0.5)
plt.subplot(gs[0,0])
plt.subplot(gs[0,1])
plt.subplot(gs[1,0])
plt.subplot(gs[1,1])

The ratios of the sizes can also be changed between the plots. So, say, for example, that we want our top row to be very tall and thin; we can specify a width and height ratio. If we pass width_ratios, we can decide how big each of these columns will appear relative to one another in terms of their width:

# Adjusting GridSpec attributes: width/height ratio
gs = mpl.gridspec.GridSpec(2,2, width_ratio=(1,2))
plt.subplot(gs[0,0])
plt.subplot(gs[0,1])
plt.subplot(gs[1,0])
plt.subplot(gs[1,1])

It sets the width of the second column to be twice the width of the first column:

When changing this to (2, 2), they will be equal, so it will literally just take a ratio of these numbers; you can pass whatever pair of ratios you want:

# Adjusting GridSpec attributes: width/height ratio
gs = mpl.gridspec.GridSpec(2,2, width_ratio=(2,2))
plt.subplot(gs[0,0])
plt.subplot(gs[0,1])
plt.subplot(gs[1,0])
plt.subplot(gs[1,1])

We will get the following output:

By changing the heights, we get the second set of plots—twice the height of the first one, as shown here:

# Adjusting GridSpec attributes: width/height ratio
gs = mpl.gridspec.GridSpec(2,2, height_ratio=(1,2))
plt.subplot(gs[0,0])
plt.subplot(gs[0,1])
plt.subplot(gs[1,0])
plt.subplot(gs[1,1])

We will see the following output:

These cannot only be integers—they can be floating-point numbers as well, as shown here:

# Adjusting GridSpec attributes: width/height ratio
gs = mpl.gridspec.GridSpec(2,2, height_ratios=(1.5,2))
plt.subplot(gs[0,0])
plt.subplot(gs[0,1])
plt.subplot(gs[1,0])
plt.subplot(gs[1,1])

By executing the preceding code, we will get the following output:

Hence, this is a quick and convenient way of setting up multi-panel plots that put the focus on the kinds of plots that we want to dominate. So, if you have a situation where, for example, you have a complex dataset where one piece of that visualization is the most important one but you have many supplemental plots that you want to show alongside it, using the subplot two grid and the grid spec object can be a nice way of building up those layouts.

The Matplotlib configuration files

In this section, we will look at the matplotlib configuration file, matplotlibrc, which contains all of the default configuration settings for how Matplotlib works on your system.

Matplotlibrc – where does it live?

matplotlibrc is multiple different configuration files; it's a hierarchy of configuration files that allows you to configure Matplotlib to behave differently for different users or different projects depending on what you need. By default, the hierarchy of which matplotlibrc config file overrides others begins with the one in the current directory, which oftentimes does not exist but ultimately will be the one that overrides all others.

The next one is within the matplotlibrc environment variable in that directory.

The third is within the config home, if you're running a Linux or BSD-based operating system with a directory called Matplotlib and a file called matplotlibrc.

Finally, with the Matplotlib installation pending on what system you're on, that installation living in some install directory will have a directory called Matplotlib data. A Matplotlib RC file that comes with Matplotlib installation is actually a fairly rich template that includes a wide variety of comments and example code which we will be discussing.

We will take a copy of the example file and put it in the .config/matplotlib file.

After opening the configuration file, we can see that it is quite big—in fact, it's 510 lines by default with the current version of Matplotlib, as shown here:

It also has a number of different options for configuring things such as fonts and appearance, as shown here:

There are also options such as the Latex behavior:

There are also options for the behavior of different backends, and we can configure the options that do not necessarily get covered by style sheets that would just be things like appearance, as follows:

The following screenshot shows the SVG writer:

Also, taking an example on what the default backend is, by default, we will set the backend to be TkAgg. We can, of course, change this depending on the system:

For example, we can change the color of text, as shown here:

# text.color : black

After uncommenting text.color (since this ultimately is the highest matplotlibrc in that hierarchy, overwriting versions of the .config file), there isn't a custom version in the directory with the Jupyter Notebooks. We will restart the kernel like we did earlier in this chapter:

Reimporting NumPy and Matplotlib, we can see here that after adding some text, hello, and inserting 0.5, we can see the colored text automatically without having to specify any other configuration options that you apply would get automatically applied without having to go in and change things by hand:

It's recommended to see all of the different options that Matplotlib provides. Go and take a look at that default template file:

Also, take a look at this documentation here: http://matplotlib.org/users/customizing.html#the-matplotlibrc-file. There is a little bit of extra text about the Matplotlib RC file. The template itself contains enough documentation. Understand this config file and look at all of the various options that are available to you.

So, if you want to configure your Matplotlib to behave in a more sensible way for your projects, it is recommended that you make a copy of this and start hacking away at it to tweak Matplotlib to do exactly what it is that you want it to.

Summary

In this chapter, we have learned about how to use style sheets to customize plot appearances, how to work with the color system within Matplotlib, how to tweak multi-panel plots to give more complex and appealing layouts for different kinds of plotting applications, and finally how to configure our Matplotlib installation.

In the next chapter, we will learn how to draw on plots to add annotations and highlights to really make the important features of a visualization pop out to the viewer.

Left arrow icon Right arrow icon
Download code icon Download Code

Key benefits

  • Practical guide with hands-on examples to design interactive plots
  • Advanced techniques to constructing complex plots
  • Explore 3D plotting and visualization using Jupyter Notebook

Description

In this book, you’ll get hands-on with customizing your data plots with the help of Matplotlib. You’ll start with customizing plots, making a handful of special-purpose plots, and building 3D plots. You’ll explore non-trivial layouts, Pylab customization, and more about tile configuration. You’ll be able to add text, put lines in plots, and also handle polygons, shapes, and annotations. Non-Cartesian and vector plots are exciting to construct, and you’ll explore them further in this book. You’ll delve into niche plots and visualize ordinal and tabular data. In this book, you’ll be exploring 3D plotting, one of the best features when it comes to 3D data visualization, along with Jupyter Notebook, widgets, and creating movies for enhanced data representation. Geospatial plotting will also be explored. Finally, you’ll learn how to create interactive plots with the help of Jupyter. Learn expert techniques for effective data visualization using Matplotlib 3 and Python with our latest offering -- Matplotlib 3.0 Cookbook

What you will learn

Deal with non-trivial and unusual plots Understanding Basemap methods Customize and represent data in 3D Construct Non-Cartesian and vector plots Design interactive plots using Jupyter Notebook Make movies for enhanced data representation

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Black & white paperback book shipped to your address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Buy Now

Product Details


Publication date : Nov 29, 2018
Length 214 pages
Edition : 1st Edition
Language : English
ISBN-13 : 9781789617696
Category :

Table of Contents

7 Chapters
Preface Chevron down icon Chevron up icon
Heavy Customization Chevron down icon Chevron up icon
Drawing on Plots Chevron down icon Chevron up icon
Special Purpose Plots Chevron down icon Chevron up icon
3D and Geospatial Plots Chevron down icon Chevron up icon
Interactive Plotting Chevron down icon Chevron up icon
Other Books You May Enjoy Chevron down icon Chevron up icon

Customer reviews

Filter icon Filter
Top Reviews
Rating distribution
Empty star icon Empty star icon Empty star icon Empty star icon Empty star icon 0
(0 Ratings)
5 star 0%
4 star 0%
3 star 0%
2 star 0%
1 star 0%

Filter reviews by


No reviews found
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact customercare@packt.com with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at customercare@packt.com using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on customercare@packt.com with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on customercare@packt.com within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on customercare@packt.com who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on customercare@packt.com within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela