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