|
1 | 1 | """
|
2 |
| -============================================== |
3 |
| -Customizing Location of Subplot Using GridSpec |
4 |
| -============================================== |
| 2 | +============================================================= |
| 3 | +Customizing Figure Layouts Using GridSpec and Other Functions |
| 4 | +============================================================= |
5 | 5 |
|
6 | 6 | How to create grid-shaped combinations of axes.
|
7 | 7 |
|
| 8 | + :func:`~matplotlib.pyplot.subplots` |
| 9 | + Perhaps the primary function used to create figures and axes. |
| 10 | + It's also similar to :func:`~matplotlib.pyplot.subplot`, |
| 11 | + but creates and places all axes on the figure at once. |
| 12 | +
|
8 | 13 | :class:`~matplotlib.gridspec.GridSpec`
|
9 |
| - specifies the geometry of the grid that a subplot will be |
10 |
| - placed in. The number of rows and number of columns of the grid |
| 14 | + Specifies the geometry of the grid that a subplot will be |
| 15 | + placed. The number of rows and number of columns of the grid |
11 | 16 | need to be set. Optionally, the subplot layout parameters
|
12 | 17 | (e.g., left, right, etc.) can be tuned.
|
13 | 18 |
|
14 | 19 | :class:`~matplotlib.gridspec.SubplotSpec`
|
15 |
| - specifies the location of the subplot in the given *GridSpec*. |
| 20 | + Specifies the location of the subplot in the given *GridSpec*. |
16 | 21 |
|
17 | 22 | :func:`~matplotlib.pyplot.subplot2grid`
|
18 |
| - a helper function that is similar to :func:`~matplotlib.pyplot.subplot` |
| 23 | + A helper function that is similar to :func:`~matplotlib.pyplot.subplot`, |
19 | 24 | but uses 0-based indexing and let subplot to occupy multiple cells.
|
| 25 | + This function is not covered in this tutorial. |
| 26 | +
|
20 | 27 | """
|
| 28 | + |
21 | 29 | import matplotlib.pyplot as plt
|
22 | 30 | import matplotlib.gridspec as gridspec
|
23 | 31 |
|
24 |
| -############################################################################### |
25 |
| -# Basic Example of using subplot2grid |
26 |
| -# =================================== |
27 |
| - |
28 |
| -# To use :func:`~matplotlib.pyplot.subplot2grid`, you provide geometry of |
29 |
| -# the grid and the location of the subplot in the grid. For a simple |
30 |
| -# single-cell subplot |
31 |
| - |
32 |
| -fig = plt.figure() |
33 |
| -ax = plt.subplot2grid((2, 2), (0, 0)) |
34 |
| - |
35 |
| -# is identical to |
36 |
| - |
37 |
| -fig = plt.figure() |
38 |
| -ax = plt.subplot(2, 2, 1) |
39 |
| - |
40 |
| -############################################################################### |
41 |
| -# Note that, unlike Matplotlib's subplot, the index starts from 0 in GridSpec. |
42 |
| -# |
43 |
| -# To create a subplot that spans multiple cells: |
44 |
| - |
45 |
| -fig = plt.figure() |
46 |
| -ax2 = plt.subplot2grid((3, 3), (1, 0), colspan=2) |
47 |
| -ax3 = plt.subplot2grid((3, 3), (1, 2), rowspan=2) |
48 |
| - |
49 |
| -############################################################################### |
50 |
| -# For example, see the output of the following commands: |
51 |
| - |
52 |
| -ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=3) |
53 |
| -ax2 = plt.subplot2grid((3, 3), (1, 0), colspan=2) |
54 |
| -ax3 = plt.subplot2grid((3, 3), (1, 2), rowspan=2) |
55 |
| -ax4 = plt.subplot2grid((3, 3), (2, 0)) |
56 |
| -ax5 = plt.subplot2grid((3, 3), (2, 1)) |
57 |
| - |
58 |
| -############################################################################### |
59 |
| -# GridSpec and SubplotSpec |
60 |
| -# ======================== |
| 32 | +############################################################################ |
| 33 | +# Basic Quickstart Guide |
| 34 | +# ====================== |
61 | 35 | #
|
62 |
| -#
9E7A
You can create :class:`~matplotlib.gridspec.GridSpec` explicitly and use |
63 |
| -# them to create a subplot. |
| 36 | +# These first two examples show how to create a basic 4-by-4 grid using |
| 37 | +# both :func:`~matplotlib.pyplot.subplots` and :mod:`~matplotlib.gridspec`. |
64 | 38 | #
|
65 |
| -# For example: |
| 39 | +# Using :func:`~matplotlib.pyplot.subplots` is quite simple. |
| 40 | +# It returns a :class:`~matplotlib.figure.Figure` instance and an array of |
| 41 | +# :class:`~matplotlib.axes.Axes` objects. |
| 42 | + |
| 43 | +fig1, f1_axes = plt.subplots(ncols=2, nrows=2) |
| 44 | +fig1.tight_layout() |
| 45 | + |
| 46 | +############################################################################ |
| 47 | +# For a simple use case such as this, :mod:`~matplotlib.gridspec` is |
| 48 | +# perhaps overly verbose. |
| 49 | +# You have to create the figure and :class:`~matplotlib.gridspec.GridSpec` |
| 50 | +# instance separately, then pass elements of gridspec instance to the |
| 51 | +# :func:`~matplotlib.figure.Figure.add_subplot` method to create the axes |
| 52 | +# objects. |
| 53 | +# The elements of the gridspec are accessed in generally the same manner as |
| 54 | +# numpy arrays. |
| 55 | + |
| 56 | +fig2 = plt.figure() |
| 57 | +spec2 = gridspec.GridSpec(ncols=2, nrows=2) |
| 58 | +f2_ax1 = fig2.add_subplot(spec2[0, 0]) |
| 59 | +f2_ax2 = fig2.add_subplot(spec2[0, 1]) |
| 60 | +f2_ax3 = fig2.add_subplot(spec2[1, 0]) |
| 61 | +f2_ax4 = fig2.add_subplot(spec2[1, 1]) |
| 62 | +fig2.tight_layout() |
| 63 | + |
| 64 | +############################################################################# |
| 65 | +# When you want to have subplots of different sizes, however, |
| 66 | +# :mod:`~matplotlib.gridspec` becomes indispensable and provides a couple |
| 67 | +# of options. |
| 68 | +# The method shown here initializes a uniform grid specification, |
| 69 | +# and then uses typical numpy indexing and slices to allocate multiple |
| 70 | +# "cells" for a given subplot. |
| 71 | + |
| 72 | +fig3 = plt.figure() |
| 73 | +spec3 = gridspec.GridSpec(ncols=3, nrows=3) |
| 74 | +anno_opts = dict(xy=(0.5, 0.5), xycoords='axes fraction', |
| 75 | + va='center', ha='center') |
| 76 | + |
| 77 | +fig3.add_subplot(spec3[0, 0]).annotate('GridSpec[0, 0]', **anno_opts) |
| 78 | +fig3.add_subplot(spec3[0, 1:]).annotate('GridSpec[0, 1:]', **anno_opts) |
| 79 | +fig3.add_subplot(spec3[1:, 0]).annotate('GridSpec[1:, 0]', **anno_opts) |
| 80 | +fig3.add_subplot(spec3[1:, 1:]).annotate('GridSpec[1:, 1:]', **anno_opts) |
| 81 | + |
| 82 | +fig3.tight_layout() |
| 83 | + |
| 84 | +############################################################################ |
| 85 | +# Other option is to use the ``width_ratios`` and ``height_ratios`` |
| 86 | +# parameters. These keyword arguments are lists of numbers. |
| 87 | +# Note that absolute values are meaningless, only their relative ratios |
| 88 | +# matter. That means that ``width_ratios=[2, 4, 8]`` is equivalent to |
| 89 | +# ``width_ratios=[1, 2, 4]`` within equally wide figures. |
| 90 | +# For the sake of demonstration, we'll blindly create the axes within |
| 91 | +# ``for`` loops since we won't need them later. |
| 92 | + |
| 93 | +fig4 = plt.figure() |
| 94 | +widths = [2, 3, 1.5] |
| 95 | +heights = [1, 3, 2] |
| 96 | +spec4 = gridspec.GridSpec(ncols=3, nrows=3, width_ratios=widths, |
| 97 | + height_ratios=heights) |
| 98 | +for row in range(3): |
| 99 | + for col in range(3): |
| 100 | + ax = fig4.add_subplot(spec4[row, col]) |
| 101 | + label = 'Width: {}\nHeight: {}'.format(widths[col], heights[row]) |
| 102 | + ax.annotate(label, (0.1, 0.5), xycoords='axes fraction', va='center') |
| 103 | + |
| 104 | +fig4.tight_layout() |
| 105 | + |
| 106 | +############################################################################ |
| 107 | +# Learning to use ``width_ratios`` and ``height_ratios`` is particularly |
| 108 | +# useful since the top-level function :func:`~matplotlib.pyplot.subplots` |
| 109 | +# accepts them within the ``gridspec_kw`` parameter. |
| 110 | +# For that matter, any parameter accepted by |
| 111 | +# :class:`~matplotlib.gridspec.GridSpec` can be passed to |
| 112 | +# :func:`~matplotlib.pyplot.subplots` via the ``gridspec_kw`` parameter. |
| 113 | +# This example recreates the previous figure without directly using a |
| 114 | +# gridspec instance. |
| 115 | + |
| 116 | +gs_kw = dict(width_ratios=widths, height_ratios=heights) |
| 117 | +fig5, f5_axes = plt.subplots(ncols=3, nrows=3, gridspec_kw=gs_kw) |
| 118 | +for r, row in enumerate(f5_axes): |
| 119 | + for c, ax in enumerate(row): |
| 120 | + label = 'Width: {}\nHeight: {}'.format(widths[c], heights[r]) |
| 121 | + ax.annotate(label, (0.1, 0.5), xycoords='axes fraction', va='center') |
| 122 | + |
| 123 | +fig5.tight_layout() |
66 | 124 |
|
67 |
| -fig = plt.figure() |
68 |
| -ax = plt.subplot2grid((2, 2), (0, 0)) |
69 |
| - |
70 |
| -# is equal to: |
71 |
| - |
72 |
| -fig = plt.figure() |
73 |
| -gs = gridspec.GridSpec(2, 2) |
74 |
| -ax = plt.subplot(gs[0, 0]) |
75 |
| - |
76 |
| -# A GridSpec instance provides array-like (2d or 1d) indexing that |
77 |
| -# returns the SubplotSpec instance. For a SubplotSpec that spans multiple |
78 |
| -# cells, use slice. |
79 |
| - |
80 |
| -ax2 = plt.subplot(gs[1, :-1]) |
81 |
| -ax3 = plt.subplot(gs[1:, -1]) |
82 |
| - |
83 |
| -############################################################################### |
84 |
| -# The above example becomes |
85 |
| - |
86 |
| -fig = plt.figure() |
87 |
| -gs = gridspec.GridSpec(3, 3) |
88 |
| -ax1 = plt.subplot(gs[0, :]) |
89 |
| -ax2 = plt.subplot(gs[1, :-1]) |
90 |
| -ax3 = plt.subplot(gs[1:, -1]) |
91 |
| -ax4 = plt.subplot(gs[-1, 0]) |
92 |
| -ax5 = plt.subplot(gs[-1, -2]) |
93 | 125 |
|
94 | 126 | ###############################################################################
|
95 |
| -# Adjust GridSpec layout |
96 |
| -# ====================== |
| 127 | +# Fine Adjustments to a Gridspec Layout |
| 128 | +# ===================================== |
97 | 129 | #
|
98 | 130 | # When a GridSpec is explicitly used, you can adjust the layout
|
99 | 131 | # parameters of subplots that are created from the GridSpec.
|
100 | 132 |
|
101 | 133 | fig = plt.figure()
|
102 |
| -gs1 = gridspec.GridSpec(3, 3) |
103 |
| -gs1.update(left=0.05, right=0.48, wspace=0.05) |
| 134 | +gs1 = gridspec.GridSpec(nrows=3, ncols=3, left=0.05, right=0.48, wspace=0.05) |
| 135 | +ax1 = fig.add_subplot(gs1[:-1, :]) |
| 136 | +ax2 = fig.add_subplot(gs1[-1, :-1]) |
| 137 | +ax3 = fig.add_subplot(gs1[-1, -1]) |
| 138 | + |
104 | 139 |
|
105 | 140 | ###############################################################################
|
106 | 141 | # This is similar to :func:`~matplotlib.pyplot.subplots_adjust`, but it only
|
107 | 142 | # affects the subplots that are created from the given GridSpec.
|
108 | 143 | #
|
109 |
| -# For example, see this code and the resulting figure: |
| 144 | +# For example, compare the left and right sides of this figure: |
110 | 145 |
|
111 | 146 | fig = plt.figure()
|
112 |
| -gs1 = gridspec.GridSpec(3, 3) |
113 |
| -gs1.update(left=0.05, right=0.48, wspace=0.05) |
114 |
| -ax1 = plt.subplot(gs1[:-1, :]) |
115 |
| -ax2 = plt.subplot(gs1[-1, :-1]) |
116 |
| -ax3 = plt.subplot(gs1[-1, -1]) |
| 147 | +gs1 = gridspec.GridSpec(nrows=3, ncols=3, left=0.05, right=0.48, |
| 148 | + wspace=0.05) |
| 149 | +ax1 = fig.add_subplot(gs1[:-1, :]) |
| 150 | +ax2 = fig.add_subplot(gs1[-1, :-1]) |
| 151 | +ax3 = fig.add_subplot(gs1[-1, -1]) |
117 | 152 |
|
118 |
| -fig = plt.figure() |
119 |
| -gs2 = gridspec.GridSpec(3, 3) |
120 |
| -gs2.update(left=0.55, right=0.98, hspace=0.05) |
121 |
| -ax4 = plt.subplot(gs2[:, :-1]) |
122 |
| -ax5 = plt.subplot(gs2[:-1, -1]) |
123 |
| -ax6 = plt.subplot(gs2[-1, -1]) |
| 153 | + |
| 154 | +gs2 = gridspec.GridSpec(nrows=3, ncols=3, left=0.55, right=0.98, |
| 155 | + hspace=0.05) |
| 156 | +ax4 = fig.add_subplot(gs2[:, :-1]) |
| 157 | +ax5 = fig.add_subplot(gs2[:-1, -1]) |
| 158 | +ax6 = fig.add_subplot(gs2[-1, -1]) |
124 | 159 |
|
125 | 160 | ###############################################################################
|
126 | 161 | # GridSpec using SubplotSpec
|
|
133 | 168 | fig = plt.figure()
|
134 | 169 | gs0 = gridspec.GridSpec(1, 2)
|
135 | 170 |
|
136 |
| -gs00 = gridspec.GridSpecFromSubplotSpec(3, 3, subplot_spec=gs0[0]) |
137 |
| -gs01 = gridspec.GridSpecFromSubplotSpec(3, 3, subplot_spec=gs0[1]) |
| 171 | +gs00 = gridspec.GridSpecFromSubplotSpec(2, 3, subplot_spec=gs0[0]) |
| 172 | +gs01 = gridspec.GridSpecFromSubplotSpec(3, 2, subplot_spec=gs0[1]) |
| 173 | + |
| 174 | +for a in range(2): |
| 175 | + for b in range(3): |
| 176 | + fig.add_subplot(gs00[a, b]) |
| 177 | + fig.add_subplot(gs01[b, a]) |
| 178 | + |
| 179 | +fig.tight_layout() |
138 | 180 |
|
139 | 181 | ###############################################################################
|
140 | 182 | # A Complex Nested GridSpec using SubplotSpec
|
@@ -183,21 +225,3 @@ def squiggle_xy(a, b, c, d, i=np.arange(0.0, 2*np.pi, 0.05)):
|
183 | 225 | ax.spines['right'].set_visible(True)
|
184 | 226 |
|
185 | 227 | plt.show()
|
186 |
| - |
187 |
| -# GridSpec with Varying Cell Sizes |
188 |
| -# ================================ |
189 |
| -# |
190 |
| -# By default, GridSpec creates cells of equal sizes. You can adjust |
191 |
|
801C
-# relative heights and widths of rows and columns. Note that absolute |
192 |
| -# values are meaningless, only their relative ratios matter. |
193 |
| - |
194 |
| -fig = plt.figure() |
195 |
| -gs = gridspec.GridSpec(2, 2, |
196 |
| - width_ratios=[1, 2], |
197 |
| - height_ratios=[4, 1] |
198 |
| - ) |
199 |
| - |
200 |
| -ax1 = plt.subplot(gs[0]) |
201 |
| -ax2 = plt.subplot(gs[1]) |
202 |
| -ax3 = plt.subplot(gs[2]) |
203 |
| -ax4 = plt.subplot(gs[3]) |
|
0 commit comments