Plotting

There are several plotting modules in python. Matplolib is the most complete/versatile package for all 2D plotting. The easiest way to construct a new plot is to have a look at http://matplotlib.org/gallery.html and get inspiration from the available examples. The official documentation can be found at: http://matplotlib.org/contents.html

Quick plots, or Matplotlib dirty usage


In [ ]:
%matplotlib

import numpy as np
import matplotlib.pyplot as plt

# To get interactive plotting (otherwise you need to 
# type plt.show() at the end of the plotting commands)
plt.ion() 

x = np.linspace(0, 10)
y = np.sin(x)

# basic X/Y line plotting with '--' dashed line and linewidth of 2
plt.plot(x, y, '--', label='first line')

# overplot a dotted line on the previous plot
plt.plot(x, np.cos(x)*np.cos(x/2), '.', linewidth=3, label='other') 

x_axis_label = plt.xlabel('x axis') #change the label of the xaxis

In [ ]:
# change your mind about the label : you do not need to replot everything !
plt.xlabel('another x axis')

In [ ]:
# or you can use the re-tuned object
x_axis_label.set_text('changed it from the object itself')

In [ ]:
# simply add the legend (from the previous label)
legend = plt.legend()

In [ ]:
plt.savefig('plot.png') # save the current figure in png
plt.savefig('plot.eps') # save the current figure in ps, no need to redo it !

In [ ]:
!ls

Proper use of Matplotlib

We will use interactive plots inline in the notebook. This feature is enabled through:


In [ ]:
%matplotlib

In [ ]:
import matplotlib.pyplot as plt
import numpy as np

# define a figure which can contains several plots, you can define resolution and so on here...
fig2 = plt.figure()

# add one axis, axes are actual plots where you can put data.fits (nx, ny, index)
ax = fig2.add_subplot(1, 1, 1)

Add a cruve with a title to the plot


In [ ]:
x = np.linspace(0, 2*np.pi)
ax.plot(x, np.sin(x), '+')
ax.set_title('this title')
plt.show()

In [ ]:
# is a simpler syntax to add one axis into the figure (we will stick to this)
fig, ax = plt.subplots()
ax.plot(x, np.sin(x), '+')
ax.set_title('simple subplot')

A long list of markers can be found at http://matplotlib.org/api/markers_api.html as for the colors, there is a nice discussion at http://stackoverflow.com/questions/22408237/named-colors-in-matplotlib

All the components of a figure can be accessed throught the 'Figure' object


In [ ]:
print(type(fig))

In [ ]:
print(dir(fig))

In [ ]:
print(fig.axes)

In [ ]:
print('This is the x-axis object', fig.axes[0].xaxis)
print('And this is the y-axis object', fig.axes[0].yaxis)

In [ ]:
# arrow pointing to the origin of the axes
ax_arrow = ax.annotate('ax = fig.axes[0]',
                       xy=(0, -1),              # tip of the arrow
                       xytext=(1, -0.5),         # location of the text
                       arrowprops={'facecolor':'red', 'shrink':0.05})

# arrow pointing to the x axis
x_ax_arrow = ax.annotate('ax.xaxis',
                         xy=(3, -1),              # tip of the arrow
                         xytext=(3, -0.5),         # location of the text
                         arrowprops={'facecolor':'red', 'shrink':0.05})
xax = ax.xaxis

# arrow pointing to the y axis
y_ax_arrow = ax.annotate('ax.yaxis',
                         xy=(0, 0),              # tip of the arrow
                         xytext=(1, 0.5),         # location of the text
                         arrowprops={'facecolor':'red', 'shrink':0.05})

Add a labels to the x and y axes


In [ ]:
# add some ascii text label
# this is equivelant to:
#     ax.set_xlabel('x')
xax.set_label_text('x')

# add latex rendered text to the y axis
ax.set_ylabel('$sin(x)$', size=20, color='g', rotation=0)

Finally dump the figure to a png file


In [ ]:
fig.savefig('myplot.png')

!ls
!eog myplot.png

Lets define a function that creates an empty base plot to which we will add stuff for each demonstration. The function returns the figure and the axes object.


In [ ]:
from matplotlib import pyplot as plt
import numpy as np

def create_base_plot():
    fig, ax = plt.subplots()
    ax.set_title('sample figure')
    return fig, ax

def plot_something():
    fig, ax = create_base_plot()
    x = np.linspace(0, 2*np.pi)
    ax.semilogx(x, np.cos(x)*np.cos(x/2), 'r--.')
    plt.show()

Log plots


In [ ]:
fig, ax = create_base_plot()

# normal-xlog plots
ax.semilogx(x, np.cos(x)*np.cos(x/2), 'r--.')

In [ ]:
# clear the plot and plot a function using the y axis in log scale
ax.clear()
ax.semilogy(x, np.exp(x))

In [ ]:
# you can (un)set it, whenever you want
#ax.set_yscale('linear')   # change they y axis to linear scale
#ax.set_yscale('log')      # change the y axis to log scale

In [ ]:
# you can also make loglog plots
#ax.clear()
#ax.loglog(x, np.exp(x)*np.sin(x))
plt.setp(ax, **dict(yscale='log', xscale='log'))

This is equivelant to:

ax.plot(x, np.exp(x)*np.sin(x))
plt.setp(ax, 'yscale', 'log', 'xscale', 'log')

here we have introduced a new method of setting property values via pyplot.setp.

setp takes as first argument a matplotlib object. Each pair of positional argument after that is treated as a key value pair for the set method name and its value. For example:

ax.set_scale('linear')

becomes

plt.setp(ax, 'scale', 'linear')

This is useful if you need to set lots of properties, such as:


In [ ]:
plt.setp(ax, 'xscale', 'linear', 'xlim', [1, 5], 'ylim', [0.1, 10], 'xlabel', 'x',
         'ylabel', 'y', 'title', 'foo',
         'xticks', [1, 2, 3, 4, 5],
         'yticks', [0.1, 1, 10],
         'yticklabels', ['low', 'medium', 'high'])

Histograms


In [ ]:
fig1, ax = create_base_plot()
n, bins, patches = ax.hist(np.random.normal(0, 0.1, 10000), bins=50)

Subplots

Making subplots is relatively easy. Just pass the shape of the grid of plots to plt.subplots() that was used in the above examples.


In [ ]:
# Create one figure with two plots/axes, with their xaxis shared
fig, (ax1, ax2) = plt.subplots(2, sharex=True)
ax1.plot(x, np.sin(x), '-.', color='r', label='first line')
other = ax2.plot(x, np.cos(x)*np.cos(x/2), 'o-', linewidth=3, label='other')
ax1.legend()
ax2.legend()

In [ ]:
# adjust the spacing between the axes
fig.subplots_adjust(hspace=0.0)

In [ ]:
# add a scatter plot to the first axis
ax1.scatter(x, np.sin(x)+np.random.normal(0, 0.1, np.size(x)))

create a 3x3 grid of plots


In [ ]:
fig, axs = plt.subplots(3, 3)

In [ ]:
print(axs.shape)

In [ ]:
# add an index to all the subplots
for ax_index, ax in enumerate(axs.flatten()):
    ax.set_title(ax_index)

In [ ]:
# remove all ticks
for ax in axs.flatten():
    plt.setp(ax, 'xticks', [], 'yticks', [])

In [ ]:
fig.subplots_adjust(hspace=0, wspace=0)

In [ ]:
# plot a curve in the diagonal subplots
for ax, func in zip(axs.diagonal(), [np.sin, np.cos, np.exp]):
    ax.plot(x, func(x))

Images and contours


In [ ]:
xx, yy = np.mgrid[-2:2:100j, -2:2:100j]
img = np.sin(xx) + np.cos(yy)

In [ ]:
fig, ax = create_base_plot()

In [ ]:
# to have 0,0 in the lower left corner and no interpolation
img_plot = ax.imshow(img, origin='lower', interpolation='None')
# to add a grid to any axis
ax.grid()

In [ ]:
img_plot.set_cmap('hot')  # changing the colormap

In [ ]:
img_plot.set_cmap('spectral')      # changing the colormap
colorb = fig.colorbar(img_plot)    # adding a color bar

In [ ]:
img_plot.set_clim(-0.5, 0.5)        # changing the dynamical range

In [ ]:
# add contour levels
img_contours = ax.contour(img, [-1, -0.5, 0.0, 0.5])
plt.clabel(img_contours, inline=True, fontsize=20)

Animation


In [ ]:
from IPython.display import HTML
import matplotlib.animation as animation

def f(x, y):
    return np.sin(x) + np.cos(y)

fig, ax = create_base_plot()
im = ax.imshow(f(xx, yy), cmap=plt.get_cmap('viridis'))

def updatefig(*args):
    global xx, yy
    xx += np.pi / 15.
    yy += np.pi / 20.
    im.set_array(f(xx, yy))
    return im,

ani = animation.FuncAnimation(fig, updatefig, interval=50, blit=True)
_ = ani.to_html5_video()

In [ ]:
# change title during animation!!
ax.set_title('runtime title')

Styles

Configuring matplotlib

Most of the matplotlib code chunk that are written are usually about styling and not actual plotting. One feature that might be of great help if you are in this case is to use the matplotlib.style module.

In this notebook, we will go through the available matplotlib styles and their corresponding configuration files. Then we will explain the two ways of using the styles and finally show you how to write a personalized style.


Pre-configured style files

An available variable returns a list of the names of some pre-configured matplotlib style files.


In [ ]:
print('\n'.join(plt.style.available))

In [ ]:
x = np.arange(0, 10, 0.01)

def f(x, t):
    return np.sin(x) * np.exp(1 - x / 10 + t / 2)

def simple_plot(style):
    plt.figure()
    with plt.style.context(style, after_reset=True):
        for t in range(5):
            plt.plot(x, f(x, t))
        plt.title('Simple plot')

In [ ]:
simple_plot('ggplot')

In [ ]:
simple_plot('dark_background')

In [ ]:
simple_plot('grayscale')

In [ ]:
simple_plot('fivethirtyeight')

In [ ]:
simple_plot('bmh')

Content of the style files

A matplotlib style file is a simple text file containing the desired matplotlib rcParam configuration, with the .mplstyle extension.

Let's display the content of the 'ggplot' style.


In [ ]:
import os
ggplotfile = os.path.join(plt.style.core.BASE_LIBRARY_PATH, 'ggplot.mplstyle')

In [ ]:
!cat $ggplotfile

Maybe the most interesting feature of this style file is the redefinition of the color cycle using hexadecimal notation. This allows the user to define is own color palette for its multi-line plots.

use versus context

There are two ways of using the matplotlib styles.

  1. plt.style.use(style)
  2. plt.style.context(style):

The use method applied at the beginning of a script will be the default choice in most cases when the style is to be set for the entire script. The only issue is that it sets the matplotlib style for the given Python session, meaning that a second call to use with a different style will only apply new style parameters and not reset the first style. That is if the axes.grid is set to True by the first style and there is nothing concerning the grid in the second style config, the grid will remain set to True which is not matplotlib default.

On the contrary, the context method will be useful when only one or two figures are to be set to a given style. It shall be used with the with statement to create a context manager in which the plot will be made.

Let's illustrate this.


In [ ]:
plt.style.use('ggplot')

plt.figure()
plt.plot(x, f(x, 0))

The 'ggplot' style has been applied to the current session. One of its features that differs from standard matplotlib configuration is to put the ticks outside the main figure (axes.axisbelow: True)


In [ ]:
with plt.style.context('dark_background'):
    plt.figure()
    plt.plot(x, f(x, 1))

Now using the 'dark_background' style as a context, we can spot the main changes (background, line color, axis color) and we can also see the outside ticks, although they are not part of this particular style. This is the 'ggplot' axes.axisbelow setup that has not been overwritten by the new style. Once the with block has ended, the style goes back to its previous status, that is the 'ggplot' style.


In [ ]:
plt.figure()
plt.plot(x, f(x, 2))

Custom style file

Starting from these configured files, it is easy to now create our own styles for textbook figures and talk figures and switch from one to another in a single code line plt.style.use('mystyle') at the beginning of the plotting script.

Where to create it ?

matplotlib will look for the user style files at the following path :


In [ ]:
print(plt.style.core.USER_LIBRARY_PATHS)

Note: The directory corresponding to this path will most probably not exist so one will need to create it.


In [ ]:
styledir = plt.style.core.USER_LIBRARY_PATHS[0]

!mkdir -p $styledir

One can now copy an existing style file to serve as a boilerplate.


In [ ]:
mystylefile = os.path.join(styledir, 'mystyle.mplstyle')

!cp $ggplotfile $mystylefile

In [ ]:
!cd $styledir

In [ ]:
%%file mystyle.mplstyle

font.size: 16.0   # large font

axes.linewidth: 2
axes.grid: True 
axes.titlesize: x-large
axes.labelsize: x-large
axes.labelcolor: 555555
axes.axisbelow: True   
    
xtick.color: 555555
xtick.direction: out

ytick.color: 555555
ytick.direction: out
    
grid.color: white
grid.linestyle: :    # dotted line

D3


In [ ]:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import mpld3
mpld3.enable_notebook()

# Scatter points
fig, ax = plt.subplots(subplot_kw=dict(axisbg='#EEEEEE'))
ax.grid(color='white', linestyle='solid')

N = 50
scatter = ax.scatter(np.random.normal(size=N),
                     np.random.normal(size=N),
                     c=np.random.random(size=N),
                     s = 1000 * np.random.random(size=N),
                     alpha=0.3,
                     cmap=plt.cm.jet)

ax.set_title("D3 Scatter Plot", size=18);

In [ ]:
import mpld3
mpld3.display(fig)

In [ ]:
from mpld3 import plugins

fig, ax = plt.subplots(subplot_kw=dict(axisbg='#EEEEEE'))
ax.grid(color='white', linestyle='solid')

N = 50
scatter = ax.scatter(np.random.normal(size=N),
                     np.random.normal(size=N),
                     c=np.random.random(size=N),
                     s = 1000 * np.random.random(size=N),
                     alpha=0.3,
                     cmap=plt.cm.jet)

ax.set_title("D3 Scatter Plot (with tooltips!)", size=20)

labels = ['point {0}'.format(i + 1) for i in range(N)]
fig.plugins = [plugins.PointLabelTooltip(scatter, labels)]

Seaborn


In [ ]:
%matplotlib

In [ ]:
plot_something()

In [ ]:
import seaborn
plot_something()