{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Create multiple subplots using ``plt.subplots``\n\n`.pyplot.subplots` creates a figure and a grid of subplots with a single call,\nwhile providing reasonable control over how the individual plots are created.\nFor more advanced use cases you can use `.GridSpec` for a more general subplot\nlayout or `.Figure.add_subplot` for adding subplots at arbitrary locations\nwithin the figure.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\nimport numpy as np\n\n# Some example data to display\nx = np.linspace(0, 2 * np.pi, 400)\ny = np.sin(x ** 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## A figure with just one subplot\n\n``subplots()`` without arguments returns a `.Figure` and a single\n`~.axes.Axes`.\n\nThis is actually the simplest and recommended way of creating a single\nFigure and Axes.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fig, ax = plt.subplots()\nax.plot(x, y)\nax.set_title('A single plot')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Stacking subplots in one direction\n\nThe first two optional arguments of `.pyplot.subplots` define the number of\nrows and columns of the subplot grid.\n\nWhen stacking in one direction only, the returned ``axs`` is a 1D numpy array\ncontaining the list of created Axes.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fig, axs = plt.subplots(2)\nfig.suptitle('Vertically stacked subplots')\naxs[0].plot(x, y)\naxs[1].plot(x, -y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you are creating just a few Axes, it's handy to unpack them immediately to\ndedicated variables for each Axes. That way, we can use ``ax1`` instead of\nthe more verbose ``axs[0]``.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fig, (ax1, ax2) = plt.subplots(2)\nfig.suptitle('Vertically stacked subplots')\nax1.plot(x, y)\nax2.plot(x, -y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To obtain side-by-side subplots, pass parameters ``1, 2`` for one row and two\ncolumns.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fig, (ax1, ax2) = plt.subplots(1, 2)\nfig.suptitle('Horizontally stacked subplots')\nax1.plot(x, y)\nax2.plot(x, -y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Stacking subplots in two directions\n\nWhen stacking in two directions, the returned ``axs`` is a 2D NumPy array.\n\nIf you have to set parameters for each subplot it's handy to iterate over\nall subplots in a 2D grid using ``for ax in axs.flat:``.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fig, axs = plt.subplots(2, 2)\naxs[0, 0].plot(x, y)\naxs[0, 0].set_title('Axis [0, 0]')\naxs[0, 1].plot(x, y, 'tab:orange')\naxs[0, 1].set_title('Axis [0, 1]')\naxs[1, 0].plot(x, -y, 'tab:green')\naxs[1, 0].set_title('Axis [1, 0]')\naxs[1, 1].plot(x, -y, 'tab:red')\naxs[1, 1].set_title('Axis [1, 1]')\n\nfor ax in axs.flat:\n ax.set(xlabel='x-label', ylabel='y-label')\n\n# Hide x labels and tick labels for top plots and y ticks for right plots.\nfor ax in axs.flat:\n ax.label_outer()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can use tuple-unpacking also in 2D to assign all subplots to dedicated\nvariables:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2)\nfig.suptitle('Sharing x per column, y per row')\nax1.plot(x, y)\nax2.plot(x, y**2, 'tab:orange')\nax3.plot(x, -y, 'tab:green')\nax4.plot(x, -y**2, 'tab:red')\n\nfor ax in fig.get_axes():\n ax.label_outer()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Sharing axes\n\nBy default, each Axes is scaled individually. Thus, if the ranges are\ndifferent the tick values of the subplots do not align.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fig, (ax1, ax2) = plt.subplots(2)\nfig.suptitle('Axes values are scaled individually by default')\nax1.plot(x, y)\nax2.plot(x + 1, -y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can use *sharex* or *sharey* to align the horizontal or vertical axis.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fig, (ax1, ax2) = plt.subplots(2, sharex=True)\nfig.suptitle('Aligning x-axis using sharex')\nax1.plot(x, y)\nax2.plot(x + 1, -y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Setting *sharex* or *sharey* to ``True`` enables global sharing across the\nwhole grid, i.e. also the y-axes of vertically stacked subplots have the\nsame scale when using ``sharey=True``.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fig, axs = plt.subplots(3, sharex=True, sharey=True)\nfig.suptitle('Sharing both axes')\naxs[0].plot(x, y ** 2)\naxs[1].plot(x, 0.3 * y, 'o')\naxs[2].plot(x, y, '+')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For subplots that are sharing axes one set of tick labels is enough. Tick\nlabels of inner Axes are automatically removed by *sharex* and *sharey*.\nStill there remains an unused empty space between the subplots.\n\nTo precisely control the positioning of the subplots, one can explicitly\ncreate a `.GridSpec` with `.Figure.add_gridspec`, and then call its\n`~.GridSpecBase.subplots` method. For example, we can reduce the height\nbetween vertical subplots using ``add_gridspec(hspace=0)``.\n\n`.label_outer` is a handy method to remove labels and ticks from subplots\nthat are not at the edge of the grid.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fig = plt.figure()\ngs = fig.add_gridspec(3, hspace=0)\naxs = gs.subplots(sharex=True, sharey=True)\nfig.suptitle('Sharing both axes')\naxs[0].plot(x, y ** 2)\naxs[1].plot(x, 0.3 * y, 'o')\naxs[2].plot(x, y, '+')\n\n# Hide x labels and tick labels for all but bottom plot.\nfor ax in axs:\n ax.label_outer()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Apart from ``True`` and ``False``, both *sharex* and *sharey* accept the\nvalues 'row' and 'col' to share the values only per row or column.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fig = plt.figure()\ngs = fig.add_gridspec(2, 2, hspace=0, wspace=0)\n(ax1, ax2), (ax3, ax4) = gs.subplots(sharex='col', sharey='row')\nfig.suptitle('Sharing x per column, y per row')\nax1.plot(x, y)\nax2.plot(x, y**2, 'tab:orange')\nax3.plot(x + 1, -y, 'tab:green')\nax4.plot(x + 2, -y**2, 'tab:red')\n\nfor ax in fig.get_axes():\n ax.label_outer()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you want a more complex sharing structure, you can first create the\ngrid of Axes with no sharing, and then call `.axes.Axes.sharex` or\n`.axes.Axes.sharey` to add sharing info a posteriori.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fig, axs = plt.subplots(2, 2)\naxs[0, 0].plot(x, y)\naxs[0, 0].set_title(\"main\")\naxs[1, 0].plot(x, y**2)\naxs[1, 0].set_title(\"shares x with main\")\naxs[1, 0].sharex(axs[0, 0])\naxs[0, 1].plot(x + 1, y + 1)\naxs[0, 1].set_title(\"unrelated\")\naxs[1, 1].plot(x + 2, y + 2)\naxs[1, 1].set_title(\"also unrelated\")\nfig.tight_layout()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Polar Axes\n\nThe parameter *subplot_kw* of `.pyplot.subplots` controls the subplot\nproperties (see also `.Figure.add_subplot`). In particular, this can be used\nto create a grid of polar Axes.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fig, (ax1, ax2) = plt.subplots(1, 2, subplot_kw=dict(projection='polar'))\nax1.plot(x, y)\nax2.plot(x, y ** 2)\n\nplt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ".. tags::\n\n component: subplot,\n component: axes,\n component: axis\n plot-type: line,\n plot-type: polar\n level: beginner\n purpose: showcase\n\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.2" } }, "nbformat": 4, "nbformat_minor": 0 }