From 44d80a6276a1e6c9fd0144461a91d9e505c0a7a7 Mon Sep 17 00:00:00 2001 From: "Christine P. Chai" Date: Tue, 25 Feb 2025 01:52:40 -0800 Subject: [PATCH 1/2] Backport PR #29666: DOC: Revising the Figure Legend Demo Example --- .../figlegend_demo.py | 48 +++++-------------- 1 file changed, 11 insertions(+), 37 deletions(-) diff --git a/galleries/examples/text_labels_and_annotations/figlegend_demo.py b/galleries/examples/text_labels_and_annotations/figlegend_demo.py index f6f74b837c10..50b3eeabc085 100644 --- a/galleries/examples/text_labels_and_annotations/figlegend_demo.py +++ b/galleries/examples/text_labels_and_annotations/figlegend_demo.py @@ -3,51 +3,25 @@ Figure legend demo ================== -Instead of plotting a legend on each axis, a legend for all the artists on all -the sub-axes of a figure can be plotted instead. +Rather than plotting a legend on each axis, a legend for all the artists +on all the sub-axes of a figure can be plotted instead. """ import matplotlib.pyplot as plt import numpy as np -fig, axs = plt.subplots(1, 2) - -x = np.arange(0.0, 2.0, 0.02) -y1 = np.sin(2 * np.pi * x) -y2 = np.exp(-x) -l1, = axs[0].plot(x, y1) -l2, = axs[0].plot(x, y2, marker='o') +fig, axs = plt.subplots(1, 2, layout='constrained') -y3 = np.sin(4 * np.pi * x) -y4 = np.exp(-2 * x) -l3, = axs[1].plot(x, y3, color='tab:green') -l4, = axs[1].plot(x, y4, color='tab:red', marker='^') +x = np.arange(0.0, 4*np.pi, 0.2) +axs[0].plot(x, np.sin(x), label='Line 1') +axs[0].plot(x, np.exp(-x/2), marker='o', label='Line 2') +axs[1].plot(x, np.sin(x), color='tab:green', label='Line 3') +axs[1].plot(x, np.exp(-x/4), color='tab:red', marker='^', label='Line 4') -fig.legend((l1, l2), ('Line 1', 'Line 2'), loc='upper left') -fig.legend((l3, l4), ('Line 3', 'Line 4'), loc='upper right') +fig.legend(loc='outside right upper') -plt.tight_layout() plt.show() # %% -# Sometimes we do not want the legend to overlap the Axes. If you use -# *constrained layout* you can specify "outside right upper", and -# *constrained layout* will make room for the legend. - -fig, axs = plt.subplots(1, 2, layout='constrained') - -x = np.arange(0.0, 2.0, 0.02) -y1 = np.sin(2 * np.pi * x) -y2 = np.exp(-x) -l1, = axs[0].plot(x, y1) -l2, = axs[0].plot(x, y2, marker='o') - -y3 = np.sin(4 * np.pi * x) -y4 = np.exp(-2 * x) -l3, = axs[1].plot(x, y3, color='tab:green') -l4, = axs[1].plot(x, y4, color='tab:red', marker='^') - -fig.legend((l1, l2), ('Line 1', 'Line 2'), loc='upper left') -fig.legend((l3, l4), ('Line 3', 'Line 4'), loc='outside right upper') - -plt.show() +# The outside positioning is discussed in detail here: +# https://matplotlib.org/stable/users/explain/axes/legend_guide.html#figure-legends From 8f240373f32ab80aeca7ea8281f48214cf04389b Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Wed, 26 Feb 2025 23:39:20 +0100 Subject: [PATCH 2/2] Backport PR #29670: DOC: change marginal scatter plot to subplot_mosaic --- .../lines_bars_and_markers/scatter_hist.py | 69 ++++++++++--------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/galleries/examples/lines_bars_and_markers/scatter_hist.py b/galleries/examples/lines_bars_and_markers/scatter_hist.py index 0a97fef5e44c..d2b4c4eab228 100644 --- a/galleries/examples/lines_bars_and_markers/scatter_hist.py +++ b/galleries/examples/lines_bars_and_markers/scatter_hist.py @@ -3,8 +3,11 @@ Scatter plot with histograms ============================ -Show the marginal distributions of a scatter plot as histograms at the sides of -the plot. +Add histograms to the x-axes and y-axes margins of a scatter plot. + +This layout features a central scatter plot illustrating the relationship +between x and y, a histogram at the top displaying the distribution of x, and a +histogram on the right showing the distribution of y. For a nice alignment of the main Axes with the marginals, two options are shown below: @@ -15,14 +18,9 @@ While `.Axes.inset_axes` may be a bit more complex, it allows correct handling of main Axes with a fixed aspect ratio. -An alternative method to produce a similar figure using the ``axes_grid1`` -toolkit is shown in the :doc:`/gallery/axes_grid1/scatter_hist_locatable_axes` -example. Finally, it is also possible to position all Axes in absolute -coordinates using `.Figure.add_axes` (not shown here). - -Let us first define a function that takes x and y data as input, as well -as three Axes, the main Axes for the scatter, and two marginal Axes. It will -then create the scatter and histograms inside the provided Axes. +Let us first define a function that takes x and y data as input, as well as +three Axes, the main Axes for the scatter, and two marginal Axes. It will then +create the scatter and histograms inside the provided Axes. """ import matplotlib.pyplot as plt @@ -55,27 +53,22 @@ def scatter_hist(x, y, ax, ax_histx, ax_histy): # %% +# Defining the Axes positions using subplot_mosaic +# ------------------------------------------------ # -# Defining the Axes positions using a gridspec -# -------------------------------------------- -# -# We define a gridspec with unequal width- and height-ratios to achieve desired -# layout. Also see the :ref:`arranging_axes` tutorial. - -# Start with a square Figure. -fig = plt.figure(figsize=(6, 6)) -# Add a gridspec with two rows and two columns and a ratio of 1 to 4 between -# the size of the marginal Axes and the main Axes in both directions. -# Also adjust the subplot parameters for a square plot. -gs = fig.add_gridspec(2, 2, width_ratios=(4, 1), height_ratios=(1, 4), - left=0.1, right=0.9, bottom=0.1, top=0.9, - wspace=0.05, hspace=0.05) -# Create the Axes. -ax = fig.add_subplot(gs[1, 0]) -ax_histx = fig.add_subplot(gs[0, 0], sharex=ax) -ax_histy = fig.add_subplot(gs[1, 1], sharey=ax) -# Draw the scatter plot and marginals. -scatter_hist(x, y, ax, ax_histx, ax_histy) +# We use the `~.pyplot.subplot_mosaic` function to define the positions and +# names of the three axes; the empty axes is specified by ``'.'``. We manually +# specify the size of the figure, and can make the different axes have +# different sizes by specifying the *width_ratios* and *height_ratios* +# arguments. The *layout* argument is set to ``'constrained'`` to optimize the +# spacing between the axes. + +fig, axs = plt.subplot_mosaic([['histx', '.'], + ['scatter', 'histy']], + figsize=(6, 6), + width_ratios=(4, 1), height_ratios=(1, 4), + layout='constrained') +scatter_hist(x, y, axs['scatter'], axs['histx'], axs['histy']) # %% @@ -109,13 +102,27 @@ def scatter_hist(x, y, ax, ax_histx, ax_histy): # %% # +# While we recommend using one of the two methods described above, there are +# number of other ways to achieve a similar layout: +# +# - The Axes can be positioned manually in relative coordinates using +# `~matplotlib.figure.Figure.add_axes`. +# - A gridspec can be used to create the layout +# (`~matplotlib.figure.Figure.add_gridspec`) and adding only the three desired +# axes (`~matplotlib.figure.Figure.add_subplot`). +# - Four subplots can be created using `~.pyplot.subplots`, and the unused +# axes in the upper right can be removed manually. +# - The ``axes_grid1`` toolkit can be used, as shown in +# :doc:`/gallery/axes_grid1/scatter_hist_locatable_axes`. +# # .. admonition:: References # # The use of the following functions, methods, classes and modules is shown # in this example: # +# - `matplotlib.figure.Figure.subplot_mosaic` +# - `matplotlib.pyplot.subplot_mosaic` # - `matplotlib.figure.Figure.add_subplot` -# - `matplotlib.figure.Figure.add_gridspec` # - `matplotlib.axes.Axes.inset_axes` # - `matplotlib.axes.Axes.scatter` # - `matplotlib.axes.Axes.hist`