Book Image

Mastering Matplotlib 2.x

By : Benjamin Walter Keller
Book Image

Mastering Matplotlib 2.x

By: Benjamin Walter Keller

Overview of this book

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
Table of Contents (7 chapters)

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.