From a15c66196fdc55651edce2aa3e266588599dd3fa Mon Sep 17 00:00:00 2001 From: hannah Date: Thu, 7 Dec 2023 01:50:36 -0500 Subject: [PATCH] doc: follow up for normalizing histogram Pull tutorial content out of example and into standalone tutorial. Co-authored-by: Elliott Sales de Andrade --- .../statistics/histogram_normalization.py | 268 +++++----------- .../artists/histogram_features.py | 298 ++++++++++++++++++ galleries/users_explain/artists/index.rst | 1 + 3 files changed, 372 insertions(+), 195 deletions(-) create mode 100644 galleries/users_explain/artists/histogram_features.py diff --git a/galleries/examples/statistics/histogram_normalization.py b/galleries/examples/statistics/histogram_normalization.py index 9418b7af002b..3f7fb39198f1 100644 --- a/galleries/examples/statistics/histogram_normalization.py +++ b/galleries/examples/statistics/histogram_normalization.py @@ -1,27 +1,23 @@ """ -.. redirect-from:: /gallery/statistics/histogram_features +======================= +Histogram normalization +======================= -=================================== -Histogram bins, density, and weight -=================================== +Histogram normalization rescales data into probabilities and therefore is a popular +technique for comparing populations of different sizes or histograms computed using +different bin edges. For more information on using `.Axes.hist` see +:ref:`histogram_features`. -The `.Axes.hist` method can flexibly create histograms in a few different ways, -which is flexible and helpful, but can also lead to confusion. In particular, -you can: +Irregularly spaced bins +----------------------- +In this example, the bins below ``x=-1.25`` are six times wider than the rest of the +bins :: -- bin the data as you want, either with an automatically chosen number of - bins, or with fixed bin edges, -- normalize the histogram so that its integral is one, -- and assign weights to the data points, so that each data point affects the - count in its bin differently. + dx = 0.1 + xbins = np.hstack([np.arange(-4, -1.25, 6*dx), np.arange(-1.25, 4, dx)]) -The Matplotlib ``hist`` method calls `numpy.histogram` and plots the results, -therefore users should consult the numpy documentation for a definitive guide. - -Histograms are created by defining bin edges, and taking a dataset of values -and sorting them into the bins, and counting or summing how much data is in -each bin. In this simple example, 9 numbers between 1 and 4 are sorted into 3 -bins: +By normalizing by density, we preserve the shape of the distribution, whereas if we do +not, then the wider bins have much higher counts than the thinner bins: """ import matplotlib.pyplot as plt @@ -29,227 +25,109 @@ rng = np.random.default_rng(19680801) -xdata = np.array([1.2, 2.3, 3.3, 3.1, 1.7, 3.4, 2.1, 1.25, 1.3]) -xbins = np.array([1, 2, 3, 4]) - -# changing the style of the histogram bars just to make it -# very clear where the boundaries of the bins are: -style = {'facecolor': 'none', 'edgecolor': 'C0', 'linewidth': 3} - -fig, ax = plt.subplots() -ax.hist(xdata, bins=xbins, **style) - -# plot the xdata locations on the x axis: -ax.plot(xdata, 0*xdata, 'd') -ax.set_ylabel('Number per bin') -ax.set_xlabel('x bins (dx=1.0)') - -# %% -# Modifying bins -# ============== -# -# Changing the bin size changes the shape of this sparse histogram, so its a -# good idea to choose bins with some care with respect to your data. Here we -# make the bins half as wide. - -xbins = np.arange(1, 4.5, 0.5) - -fig, ax = plt.subplots() -ax.hist(xdata, bins=xbins, **style) -ax.plot(xdata, 0*xdata, 'd') -ax.set_ylabel('Number per bin') -ax.set_xlabel('x bins (dx=0.5)') - -# %% -# We can also let numpy (via Matplotlib) choose the bins automatically, or -# specify a number of bins to choose automatically: - -fig, ax = plt.subplot_mosaic([['auto', 'n4']], - sharex=True, sharey=True, layout='constrained') - -ax['auto'].hist(xdata, **style) -ax['auto'].plot(xdata, 0*xdata, 'd') -ax['auto'].set_ylabel('Number per bin') -ax['auto'].set_xlabel('x bins (auto)') - -ax['n4'].hist(xdata, bins=4, **style) -ax['n4'].plot(xdata, 0*xdata, 'd') -ax['n4'].set_xlabel('x bins ("bins=4")') - -# %% -# Normalizing histograms: density and weight -# ========================================== -# -# Counts-per-bin is the default length of each bar in the histogram. However, -# we can also normalize the bar lengths as a probability density function using -# the ``density`` parameter: - -fig, ax = plt.subplots() -ax.hist(xdata, bins=xbins, density=True, **style) -ax.set_ylabel('Probability density [$V^{-1}$])') -ax.set_xlabel('x bins (dx=0.5 $V$)') - -# %% -# This normalization can be a little hard to interpret when just exploring the -# data. The value attached to each bar is divided by the total number of data -# points *and* the width of the bin, and thus the values _integrate_ to one -# when integrating across the full range of data. -# e.g. :: -# -# density = counts / (sum(counts) * np.diff(bins)) -# np.sum(density * np.diff(bins)) == 1 -# -# This normalization is how `probability density functions -# `_ are defined in -# statistics. If :math:`X` is a random variable on :math:`x`, then :math:`f_X` -# is is the probability density function if :math:`P[a`_, and also calculate the -# known probability density function: - xdata = rng.normal(size=1000) xpdf = np.arange(-4, 4, 0.1) pdf = 1 / (np.sqrt(2 * np.pi)) * np.exp(-xpdf**2 / 2) -# %% -# If we don't use ``density=True``, we need to scale the expected probability -# distribution function by both the length of the data and the width of the -# bins: +dx = 0.1 +xbins = np.hstack([np.arange(-4, -1.25, 6*dx), np.arange(-1.25, 4, dx)]) fig, ax = plt.subplot_mosaic([['False', 'True']], layout='constrained') -dx = 0.1 -xbins = np.arange(-4, 4, dx) -ax['False'].hist(xdata, bins=xbins, density=False, histtype='step', label='Counts') -# scale and plot the expected pdf: -ax['False'].plot(xpdf, pdf * len(xdata) * dx, label=r'$N\,f_X(x)\,\delta x$') -ax['False'].set_ylabel('Count per bin') -ax['False'].set_xlabel('x bins [V]') -ax['False'].legend() +fig.suptitle("Histogram with irregularly spaced bins") + + +ax['False'].hist(xdata, bins=xbins, density=False, histtype='step', label='Counts') +ax['False'].plot(xpdf, pdf * len(xdata) * dx, label=r'$N\,f_X(x)\,\delta x_0$', + alpha=.5) ax['True'].hist(xdata, bins=xbins, density=True, histtype='step', label='density') -ax['True'].plot(xpdf, pdf, label='$f_X(x)$') -ax['True'].set_ylabel('Probability density [$V^{-1}$]') -ax['True'].set_xlabel('x bins [$V$]') -ax['True'].legend() +ax['True'].plot(xpdf, pdf, label='$f_X(x)$', alpha=.5) -# %% -# One advantage of using the density is therefore that the shape and amplitude -# of the histogram does not depend on the size of the bins. Consider an -# extreme case where the bins do not have the same width. In this example, the -# bins below ``x=-1.25`` are six times wider than the rest of the bins. By -# normalizing by density, we preserve the shape of the distribution, whereas if -# we do not, then the wider bins have much higher counts than the thinner bins: -fig, ax = plt.subplot_mosaic([['False', 'True']], layout='constrained') -dx = 0.1 -xbins = np.hstack([np.arange(-4, -1.25, 6*dx), np.arange(-1.25, 4, dx)]) -ax['False'].hist(xdata, bins=xbins, density=False, histtype='step', label='Counts') -ax['False'].plot(xpdf, pdf * len(xdata) * dx, label=r'$N\,f_X(x)\,\delta x_0$') -ax['False'].set_ylabel('Count per bin') -ax['False'].set_xlabel('x bins [V]') +ax['False'].set(xlabel='x [V]', ylabel='Count per bin', title="density=False") + +# add the bin widths on the minor axes to highlight irregularity +ax['False'].set_xticks(xbins, minor=True) ax['False'].legend() -ax['True'].hist(xdata, bins=xbins, density=True, histtype='step', label='density') -ax['True'].plot(xpdf, pdf, label='$f_X(x)$') -ax['True'].set_ylabel('Probability density [$V^{-1}$]') -ax['True'].set_xlabel('x bins [$V$]') +ax['True'].set(xlabel='x [$V$]', ylabel='Probability density [$V^{-1}$]', + title="density=True") +ax['False'].set_xticks(xbins, minor=True) ax['True'].legend() + # %% -# Similarly, if we want to compare histograms with different bin widths, we may -# want to use ``density=True``: +# Different bin widths +# -------------------- +# +# Here we use normalization to compare histograms with binwidths of 0.1, 0.4, and 1.2: fig, ax = plt.subplot_mosaic([['False', 'True']], layout='constrained') +fig.suptitle("Comparing histograms with different bin widths") # expected PDF ax['True'].plot(xpdf, pdf, '--', label='$f_X(x)$', color='k') for nn, dx in enumerate([0.1, 0.4, 1.2]): xbins = np.arange(-4, 4, dx) # expected histogram: - ax['False'].plot(xpdf, pdf*1000*dx, '--', color=f'C{nn}') - ax['False'].hist(xdata, bins=xbins, density=False, histtype='step') - - ax['True'].hist(xdata, bins=xbins, density=True, histtype='step', label=dx) + ax['False'].plot(xpdf, pdf*1000*dx, '--', color=f'C{nn}', alpha=.5) + ax['False'].hist(xdata, bins=xbins, density=False, histtype='step', label=dx) -# Labels: -ax['False'].set_xlabel('x bins [$V$]') -ax['False'].set_ylabel('Count per bin') -ax['True'].set_ylabel('Probability density [$V^{-1}$]') -ax['True'].set_xlabel('x bins [$V$]') -ax['True'].legend(fontsize='small', title='bin width:') + ax['True'].hist(xdata, bins=xbins, density=True, histtype='step') +ax['False'].set(xlabel='x [$V$]', ylabel='Count per bin', + title="density=False") +ax['True'].set(xlabel='x [$V$]', ylabel='Probability density [$V^{-1}$]', + title='density=True') +ax['False'].legend(fontsize='small', title='bin width:') # %% -# Sometimes people want to normalize so that the sum of counts is one. This is -# analogous to a `probability mass function -# `_ for a discrete -# variable where the sum of probabilities for all the values equals one. Using -# ``hist``, we can get this normalization if we set the *weights* to 1/N. -# Note that the amplitude of this normalized histogram still depends on -# width and/or number of the bins: +# Populations of different sizes +# ------------------------------ +# +# Here we compare the distribution of ``xdata`` with a population of 1000, and +# ``xdata2`` with 100 members. We demonstrate using *density* to generate the +# probability density function(`pdf`_) and *weight* to generate an analog to the +# probability mass function (`pmf`_). +# +# .. _pdf: https://en.wikipedia.org/wiki/Probability_density_function +# .. _pmf: https://en.wikipedia.org/wiki/Probability_mass_function -fig, ax = plt.subplots(layout='constrained', figsize=(3.5, 3)) +xdata2 = rng.normal(size=100) -for nn, dx in enumerate([0.1, 0.4, 1.2]): - xbins = np.arange(-4, 4, dx) - ax.hist(xdata, bins=xbins, weights=1/len(xdata) * np.ones(len(xdata)), - histtype='step', label=f'{dx}') -ax.set_xlabel('x bins [$V$]') -ax.set_ylabel('Bin count / N') -ax.legend(fontsize='small', title='bin width:') +fig, ax = plt.subplot_mosaic([['no_norm', 'density', 'weight']], layout='constrained') -# %% -# The value of normalizing histograms is comparing two distributions that have -# different sized populations. Here we compare the distribution of ``xdata`` -# with a population of 1000, and ``xdata2`` with 100 members. +fig.suptitle("Comparing histograms of populations of different sizes") -xdata2 = rng.normal(size=100) +xbins = np.arange(-4, 4, 0.25) -fig, ax = plt.subplot_mosaic([['no_norm', 'density', 'weight']], - layout='constrained', figsize=(8, 4)) +for xd in [xdata, xdata2]: + ax['no_norm'].hist(xd, bins=xbins, histtype='step') + ax['density'].hist(xd, bins=xbins, histtype='step', density=True) + ax['weight'].hist(xd, bins=xbins, histtype='step', weights=np.ones(len(xd))/len(xd), + label=f'N={len(xd)}') -xbins = np.arange(-4, 4, 0.25) -ax['no_norm'].hist(xdata, bins=xbins, histtype='step') -ax['no_norm'].hist(xdata2, bins=xbins, histtype='step') -ax['no_norm'].set_ylabel('Counts') -ax['no_norm'].set_xlabel('x bins [$V$]') -ax['no_norm'].set_title('No normalization') - -ax['density'].hist(xdata, bins=xbins, histtype='step', density=True) -ax['density'].hist(xdata2, bins=xbins, histtype='step', density=True) -ax['density'].set_ylabel('Probability density [$V^{-1}$]') -ax['density'].set_title('Density=True') -ax['density'].set_xlabel('x bins [$V$]') - -ax['weight'].hist(xdata, bins=xbins, histtype='step', - weights=1 / len(xdata) * np.ones(len(xdata)), - label='N=1000') -ax['weight'].hist(xdata2, bins=xbins, histtype='step', - weights=1 / len(xdata2) * np.ones(len(xdata2)), - label='N=100') -ax['weight'].set_xlabel('x bins [$V$]') -ax['weight'].set_ylabel('Counts / N') +ax['no_norm'].set(xlabel='x [$V$]', ylabel='Counts', title='No normalization') +ax['density'].set(xlabel='x [$V$]', + ylabel='Probability density [$V^{-1}$]', title='Density=True') +ax['weight'].set(xlabel='x bins [$V$]', ylabel='Counts / N', title='Weight = 1/N') + ax['weight'].legend(fontsize='small') -ax['weight'].set_title('Weight = 1/N') plt.show() # %% # +# .. tags:: plot-type: histogram +# # .. admonition:: References # # The use of the following functions, methods, classes and modules is shown # in this example: # # - `matplotlib.axes.Axes.hist` / `matplotlib.pyplot.hist` -# - `matplotlib.axes.Axes.set_title` -# - `matplotlib.axes.Axes.set_xlabel` -# - `matplotlib.axes.Axes.set_ylabel` +# - `matplotlib.axes.Axes.set` # - `matplotlib.axes.Axes.legend` +# diff --git a/galleries/users_explain/artists/histogram_features.py b/galleries/users_explain/artists/histogram_features.py new file mode 100644 index 000000000000..1dc634896236 --- /dev/null +++ b/galleries/users_explain/artists/histogram_features.py @@ -0,0 +1,298 @@ +""" +.. redirect-from:: /gallery/statistics/histogram_features + +.. _histogram_features: + +========= +Histogram +========= + +Histograms are used to visualize the distribution of a dataset across a set of fixed +bins. Histograms are created by defining the bin edges, sorting the values in a dataset +into the bins, and then counting or summing how much data is in each bin. The +`.Axes.hist` method provides the following parameters for defining bins and counting: + +:bins: choose the number of bins or pass a list of bin edges +:density: normalize the histogram so that its integral is one, +:weights: assign how much each value contributes to its bin count + +The Matplotlib ``hist`` method forwards the data and the *bins*, *range*, *density* and +*weights* parameters to `numpy.histogram` and plots the results; therefore, users should +consult the numpy documentation for a definitive guide. + +In this example, 9 numbers between 1 and 4 are sorted into 3 bins: +""" + +import matplotlib.pyplot as plt +import numpy as np + +rng = np.random.default_rng(19680801) + +xdata = np.array([1.2, 2.3, 3.3, 3.1, 1.7, 3.4, 2.1, 1.25, 1.3]) +xbins = np.array([1, 2, 3, 4]) + +# changing the style of the histogram bars just to make it +# very clear where the boundaries of the bins are: +style = {'facecolor': 'none', 'edgecolor': 'C0', 'linewidth': 3} +fw, fh = (6, 3) + +fig, ax = plt.subplots(layout='constrained', figsize=(fw, fh)) + +# count the number of values in xdata between each value in xbins +ax.hist(xdata, bins=xbins, **style) + +# plot the xdata events +ax.eventplot(xdata, color='C1', alpha=.5) + +# add labels and set the x tick marks to bin edges +ax.set(xlabel='x bins (dx=1.0)', xticks=xbins, + ylabel='count per bin', title='Histogram') + +# %% +# bin widths +# ========== +# +# Changing the bin size changes the shape of this sparse histogram, so it is a +# good idea to choose bins with some care with respect to your data. The `.Axes.hist` +# *bins* parameter accepts either the number of bins or a list of bin edges. +# +# +# Fixed bin edges +# --------------- +# +# Here the bins are set to the list of edges [1, 1.5, 2, 2.5, 3, 3.5, 4]. +# +# .. code-block:: python +# +# xbins = np.arange(1, 4.5, 0.5) +# ax.hist(xdata, bins=xbins, **style) +# +# As illustrated, this generates a histogram where the bins are half as wide as the +# previous example: + +xbins = np.arange(1, 4.5, 0.5) + +fig, ax = plt.subplots(layout='constrained', figsize=(fw, fh)) + +ax.hist(xdata, bins=xbins, **style) + +ax.eventplot(xdata, color='C1', alpha=.5) + +ax.set(xlabel='x bins (dx=0.5)', xticks=xbins, ylabel='count', + title='Histogram with fixed bin edges') + +# %% +# +# Number of bins +# -------------- +# +# We can also let numpy (via Matplotlib) choose the bins automatically: +# +# .. code-block:: python +# +# ax['auto'].hist(xdata) +# +# or specify the number of bins, the edges of which are then chosen automatically: +# +# .. code-block:: python +# +# ax['n4'].hist(xdata, bins=4) +# +# In the following example, we show both methods of choosing the bins: + +fig, ax = plt.subplot_mosaic([['auto'], ['n4']], + sharey=True, layout='constrained', figsize=(fw, fh)) +fig.suptitle("Dynamically computed bins") + + +_, bin1, _ = ax['auto'].hist(xdata, **style) +_, bin2, _ = ax['n4'].hist(xdata, bins=4, **style) + + +ax['auto'].eventplot(xdata, color='C1', alpha=.5) +ax['n4'].eventplot(xdata, color='C1', alpha=.5) + +ax['auto'].set(xlabel='x bins', xticks=bin1, ylabel='count', + title='bins="auto"') +ax['n4'].set(xlabel='x bins', xticks=bin2, ylabel='count', + title='bins=4') +# %% +# The `.Axes.hist` method returns the data being binned, the bin edges, and the list +# of artists used to create the histogram. Here we use the returned bins to generate the +# xticks. +# +# Computing bin contents +# ====================== +# +# Counts-per-bin is the default length of each bar in the histogram. However, the +# *density* and *weights* parameters can be used to change how the contents of each bin +# are counted, and therefore *density* and *weights* affect the length of each bar. +# +# density +# ------- +# +# We can normalize the bar lengths as a probability density function using +# the ``density`` parameter. The value (count) attached to each bar is divided by the +# total number of data points *and* the width of the bin, and thus the values +# *integrate* to one when integrating across the full range of data. +# +# e.g. :: +# +# density = counts / (sum(counts) * np.diff(bins)) +# np.sum(density * np.diff(bins)) == 1 +# +# This normalization is how `probability density functions +# `_ are defined in +# statistics. +# +# +# To normalize the bar length, we set *density* to True: +# +# .. code-block:: python +# +# ax['True'].hist(xdata, bins=xbins, density=True, **style) +# +# As shown, setting the density kwarg only changes the count: + +fig, ax = plt.subplot_mosaic([['False', 'True']], layout='constrained', + figsize=(fw, fh)) +fig.suptitle('Histogram normalization using density') + + +ax['False'].hist(xdata, bins=xbins, **style) +# Normalize the histogram +ax['True'].hist(xdata, bins=xbins, density=True, **style) + + +ax['False'].set(xlabel='x bins (dx=0.5)', xticks=xbins, + ylabel='count per bin', title='density=False') + +ax['True'].set(xlabel='x bins (dx=0.5 $V$)', xticks=xbins, + ylabel='Probability density [$V^{-1}$])', title='density=True') + + +# The usefulness of this normalization is a little more clear when we draw from +# a known distribution and try to compare with theory. So, choose 1000 points +# from a `normal distribution +# `_, and also calculate the +# known probability density function: + +xdata = rng.normal(size=1000) +xpdf = np.arange(-4, 4, 0.1) +pdf = 1 / (np.sqrt(2 * np.pi)) * np.exp(-xpdf**2 / 2) + +# %% +# If we don't use ``density=True``, we need to scale the expected probability +# distribution function by both the length of the data and the width of the +# bins to fit it to the histogram: +# +# .. code-block:: python +# +# ax['False'].hist(xdata, bins=xbins, density=False, histtype='step', label='counts') +# ax['False'].plot(xpdf, pdf * len(xdata) * dx, +# label=r'$N\,f_X(x)\,\delta x$', alpha=.5) +# +# while we do not need to scale the pdf to fit it to the normalized histogram +# +# .. code-block:: python +# +# ax['True'].hist(xdata, bins=xbins, density=True, histtype='step', label='density') +# ax['True'].plot(xpdf, pdf, label='$f_X(x)$', alpha=.5) +# +# The effect of this scaling is that the two plots look identical, but are on different +# y-axis scales: + +dx = 0.1 +xbins = np.arange(-4, 4, dx) + +fig, ax = plt.subplot_mosaic([['False', 'True']], layout='constrained', + figsize=(fw, fh)) +fig.suptitle("Histogram normalization using scaling") + +ax['False'].hist(xdata, bins=xbins, density=False, histtype='step', label='counts') +# scale and plot the expected pdf: +ax['False'].plot(xpdf, pdf * len(xdata) * dx, label=r'$N\,f_X(x)\,\delta x$', alpha=.5) + + +ax['True'].hist(xdata, bins=xbins, density=True, histtype='step', label='density') +ax['True'].plot(xpdf, pdf, label='$f_X(x)$', alpha=.5) + + +ax['False'].set(xlabel='x [$V$]', ylabel='Count per bin', title="density=False") +ax['False'].legend() +ax['True'].set(xlabel='x [$V$]', ylabel='Probability density [$V^{-1}$]', + title="density=True") +ax['True'].legend() + +# %% +# weights +# ------- +# +# We can change how much each data value contributes to its bin computation by passing +# in a list of weights, one per value, to the *weights* parameter. Here we set the +# weights to only count values less than 2 +# +# .. code-block:: Python +# +# xdata = np.array([1.2, 2.3, 3.3, 3.1, 1.7, 3.4, 2.1, 1.25, 1.3]) +# weights = (xdata<2).astype(int) + +xdata = np.array([1.2, 2.3, 3.3, 3.1, 1.7, 3.4, 2.1, 1.25, 1.3]) +xbins = np.arange(1, 4.5, 0.5) + +fig, ax = plt.subplot_mosaic([['False', 'True']], layout='constrained', + figsize=(fw, fh)) +fig.suptitle('Compute histograms using weights') + + +ax['False'].hist(xdata, bins=xbins, **style) +# Normalize the histogram +ax['True'].hist(xdata, bins=xbins, weights=(xdata < 2).astype(int), **style) + + +ax['False'].set(xlabel='x bins (dx=0.5)', xticks=xbins, + ylabel='count per bin', title="unweighted") + +ax['True'].set(xlabel='x bins (dx=0.5 $V$)', xticks=xbins, + ylabel='weighted count per bin', title='weights=int(x)') + +# %% +# Sometimes people want to normalize so that the sum of counts is one. This is +# analogous to a `probability mass function +# `_ for a discrete +# variable where the sum of probabilities for all the values equals one. +# +# Using ``hist``, we can get this normalization if we set the *weights* to 1/N. +# +# .. code-block:: python +# +# ax.hist(xdata, bins=xbins, weights=np.ones(len(xdata))/len(xdata), +# histtype='step', label=f'{dx}') +# +# Note that the amplitude of this normalized histogram still depends on +# width and/or number of bins: + +fig, ax = plt.subplots(layout='constrained', figsize=(fw, fh)) + +for nn, dx in enumerate([0.1, 0.4, 1.2]): + xbins = np.arange(-4, 4, dx) + ax.hist(xdata, bins=xbins, weights=np.ones(len(xdata))/len(xdata), + histtype='step', label=f'{dx}') + +ax.set(xlabel='x [$V$]', ylabel='Bin count / N', + title="Histogram normalization using weights") +ax.legend(fontsize='small', title='bin width:') + +# %% +# +# .. tags:: plot-type: histogram +# +# .. admonition:: References +# +# The use of the following functions, methods, classes and modules is shown +# in this example: +# +# - `matplotlib.axes.Axes.hist` / `matplotlib.pyplot.hist` +# - `matplotlib.axes.Axes.set` +# - `matplotlib.axes.Axes.legend` +# diff --git a/galleries/users_explain/artists/index.rst b/galleries/users_explain/artists/index.rst index d3f2918c9a91..ad3a910c0a51 100644 --- a/galleries/users_explain/artists/index.rst +++ b/galleries/users_explain/artists/index.rst @@ -20,4 +20,5 @@ and :doc:`Axes <../axes/index>` are Artists, and generally contain Paths Path effects guide Understanding the extent keyword argument of imshow + Understanding bin edges and values in histogram transforms_tutorial pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy