diff --git a/examples/subplots_axes_and_figures/subplots_demo.py b/examples/subplots_axes_and_figures/subplots_demo.py index cf5a3505952f..2f4b5efbdb2a 100644 --- a/examples/subplots_axes_and_figures/subplots_demo.py +++ b/examples/subplots_axes_and_figures/subplots_demo.py @@ -1,103 +1,189 @@ """ -============= -Subplots Demo -============= - -Examples illustrating the use of plt.subplots(). - -This function creates a figure and a grid of subplots with a single call, while -providing reasonable control over how the individual plots are created. For -very refined tuning of subplot creation, you can still use add_subplot() -directly on a new figure. +================================================ +Creating multiple subplots using ``plt.subplot`` +================================================ + +`.pyplot.subplots` creates a figure and a grid of subplots with a single call, +while providing reasonable control over how the individual plots are created. +For more advanced use cases you can use `.GridSpec` for a more general subplot +layout or `.Figure.add_subplot` for adding subplots at arbitrary locations +within the figure. """ +# sphinx_gallery_thumbnail_number = 11 + import matplotlib.pyplot as plt import numpy as np -# Simple data to display in various forms +# Some example data to display x = np.linspace(0, 2 * np.pi, 400) y = np.sin(x ** 2) -plt.close('all') +############################################################################### +# A figure with just one subplot +# """""""""""""""""""""""""""""" +# +# ``subplots()`` without arguments returns a `.Figure` and a single +# `~.axes.Axes`. +# +# This is actually the simplest and recommended way of creating a single +# Figure and Axes. + +fig, ax = plt.subplots() +ax.plot(x, y) +ax.set_title('A single plot') ############################################################################### -# Just a figure and one subplot +# Stacking subplots in one direction +# """""""""""""""""""""""""""""""""" +# +# The first two optional arguments of `.pyplot.subplots` define the number of +# rows and columns of the subplot grid. +# +# When stacking in one direction only, the returned `axs` is a 1D numpy array +# containing the list of created Axes. + +fig, axs = plt.subplots(2) +fig.suptitle('Vertically stacked subplots') +axs[0].plot(x, y) +axs[1].plot(x, -y) -f, ax = plt.subplots() -ax.plot(x, y) -ax.set_title('Simple plot') +############################################################################### +# If you are creating just a few Axes, it's handy to unpack them immediately to +# dedicated variables for each Axes. That way, we can use ``ax1`` instead of +# the more verbose ``axs[0]``. + +fig, (ax1, ax2) = plt.subplots(2) +fig.suptitle('Vertically stacked subplots') +ax1.plot(x, y) +ax2.plot(x, -y) ############################################################################### -# Two subplots, the axes array is 1-d +# To obtain side-by-side subplots, pass parameters ``1, 2`` for one row and two +# columns. -f, axarr = plt.subplots(2, sharex=True) -f.suptitle('Sharing X axis') -axarr[0].plot(x, y) -axarr[1].scatter(x, y) +fig, (ax1, ax2) = plt.subplots(1, 2) +fig.suptitle('Horizontally stacked subplots') +ax1.plot(x, y) +ax2.plot(x, -y) + +############################################################################### +# Stacking subplots in two directions +# """"""""""""""""""""""""""""""""""" +# +# When stacking in two directions, the returned `axs` is a 2D numpy array. +# +# If you have to set parameters for each subplot it's handy to iterate over +# all subplots in a 2D grid using ``for ax in axs.flat:``. + +fig, axs = plt.subplots(2, 2) +axs[0, 0].plot(x, y) +axs[0, 0].set_title('Axis [0,0]') +axs[0, 1].plot(x, y, 'tab:orange') +axs[0, 1].set_title('Axis [0,1]') +axs[1, 0].plot(x, -y, 'tab:green') +axs[1, 0].set_title('Axis [1,0]') +axs[1, 1].plot(x, -y, 'tab:red') +axs[1, 1].set_title('Axis [1,1]') + +for ax in axs.flat: + ax.set(xlabel='x-label', ylabel='y-label') + +# Hide x labels and tick labels for top plots and y ticks for right plots. +for ax in axs.flat: + ax.label_outer() ############################################################################### -# Two subplots, unpack the axes array immediately +# You can use tuple-unpacking also in 2D to assign all subplots to dedicated +# variables: -f, (ax1, ax2) = plt.subplots(1, 2, sharey=True) -f.suptitle('Sharing Y axis') +fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2) +fig.suptitle('Sharing x per column, y per row') ax1.plot(x, y) -ax2.scatter(x, y) +ax2.plot(x, y**2, 'tab:orange') +ax3.plot(x, -y, 'tab:green') +ax4.plot(x, -y**2, 'tab:red') + +for ax in axs.flat: + ax.label_outer() + +############################################################################### +# Sharing axes +# """""""""""" +# +# By default, each Axes is scaled individually. Thus, if the ranges are +# different the tick values of the subplots do not align. + +fig, (ax1, ax2) = plt.subplots(2) +fig.suptitle('Axes values are scaled individually by default') +ax1.plot(x, y) +ax2.plot(x + 1, -y) + +############################################################################### +# You can use *sharex* or *sharey* to align the horizontal or vertical axis. + +fig, (ax1, ax2) = plt.subplots(2, sharex=True) +fig.suptitle('Aligning x-axis using sharex') +ax1.plot(x, y) +ax2.plot(x + 1, -y) ############################################################################### -# Three subplots sharing both x/y axes - -f, axarr = plt.subplots(3, sharex=True, sharey=True) -f.suptitle('Sharing both axes') -axarr[0].plot(x, y) -axarr[1].scatter(x, y) -axarr[2].scatter(x, 2 * y ** 2 - 1, color='r') -# Bring subplots close to each other. -f.subplots_adjust(hspace=0) +# Setting *sharex* or *sharey* to ``True`` enables global sharing across the +# whole grid, i.e. also the y-axes of vertically stacked subplots have the +# same scale when using ``sharey=True``. + +fig, axs = plt.subplots(3, sharex=True, sharey=True) +fig.suptitle('Sharing both axes') +axs[0].plot(x, y ** 2) +axs[1].plot(x, 0.3 * y, 'o') +axs[2].plot(x, y, '+') + +############################################################################### +# For subplots that are sharing axes one set of tick labels is enough. Tick +# labels of inner Axes are automatically removed by *sharex* and *sharey*. +# Still there remains an unused empty space between the subplots. +# +# The parameter *gridspec_kw* of `.pyplot.subplots` controls the grid +# properties (see also `.GridSpec`). For example, we can reduce the height +# between vertical subplots using ``gridspec_kw={'hspace': 0}``. +# +# `.label_outer` is a handy method to remove labels and ticks from subplots +# that are not at the edge of the grid. + +fig, axs = plt.subplots(3, sharex=True, sharey=True, gridspec_kw={'hspace': 0}) +fig.suptitle('Sharing both axes') +axs[0].plot(x, y ** 2) +axs[1].plot(x, 0.3 * y, 'o') +axs[2].plot(x, y, '+') + # Hide x labels and tick labels for all but bottom plot. -for ax in axarr: +for ax in axs: ax.label_outer() ############################################################################### -# Row and column sharing +# Apart from ``True`` and ``False``, both *sharex* and *sharey* accept the +# values 'row' and 'col' to share the values only per row or column. -f, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, sharex='col', sharey='row') -f.suptitle('Sharing x per column, y per row') +fig, axs = plt.subplots(2, 2, sharex='col', sharey='row', + gridspec_kw={'hspace': 0, 'wspace': 0}) +(ax1, ax2), (ax3, ax4) = axs +fig.suptitle('Sharing x per column, y per row') ax1.plot(x, y) -ax2.scatter(x, y) -ax3.scatter(x, 2 * y ** 2 - 1, color='r') -ax4.plot(x, 2 * y ** 2 - 1, color='r') +ax2.plot(x, y**2, 'tab:orange') +ax3.plot(x + 1, -y, 'tab:green') +ax4.plot(x + 2, -y**2, 'tab:red') -############################################################################### -# Four axes, returned as a 2-d array - -f, axarr = plt.subplots(2, 2) -axarr[0, 0].plot(x, y) -axarr[0, 0].set_title('Axis [0,0]') -axarr[0, 1].scatter(x, y) -axarr[0, 1].set_title('Axis [0,1]') -axarr[1, 0].plot(x, y ** 2) -axarr[1, 0].set_title('Axis [1,0]') -axarr[1, 1].scatter(x, y ** 2) -axarr[1, 1].set_title('Axis [1,1]') -for ax in axarr.flat: - ax.set(xlabel='x-label', ylabel='y-label') -# Hide x labels and tick labels for top plots and y ticks for right plots. -for ax in axarr.flat: +for ax in axs.flat: ax.label_outer() ############################################################################### -# Four polar axes - -f, axarr = plt.subplots(2, 2, subplot_kw=dict(projection='polar')) -axarr[0, 0].plot(x, y) -axarr[0, 0].set_title('Axis [0,0]') -axarr[0, 1].scatter(x, y) -axarr[0, 1].set_title('Axis [0,1]') -axarr[1, 0].plot(x, y ** 2) -axarr[1, 0].set_title('Axis [1,0]') -axarr[1, 1].scatter(x, y ** 2) -axarr[1, 1].set_title('Axis [1,1]') -# Fine-tune figure; make subplots farther from each other. -f.subplots_adjust(hspace=0.3) - -plt.show() +# Polar axes +# """""""""" +# +# The parameter *subplot_kw* of `.pyplot.subplots` controls the subplot +# properties (see also `.Figure.add_subplot`). In particular, this can be used +# to create a grid of polar Axes. + +fig, (ax1, ax2) = plt.subplots(1, 2, subplot_kw=dict(projection='polar')) +ax1.plot(x, y) +ax2.plot(x, y ** 2)