
.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "tutorials/lifecycle.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. meta::
        :keywords: codex

    .. note::
        :class: sphx-glr-download-link-note

        :ref:`Go to the end <sphx_glr_download_tutorials_lifecycle.py>`
        to download the full example code.

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_tutorials_lifecycle.py:


.. redirect-from:: /tutorials/introductory/lifecycle

=======================
The Lifecycle of a Plot
=======================

This tutorial aims to show the beginning, middle, and end of a single
visualization using Matplotlib. We'll begin with some raw data and
end by saving a figure of a customized visualization. Along the way we try
to highlight some neat features and best-practices using Matplotlib.

.. currentmodule:: matplotlib

.. note::

    This tutorial is based on
    `this excellent blog post
    <https://pbpython.com/effective-matplotlib.html>`_
    by Chris Moffitt. It was transformed into this tutorial by Chris Holdgraf.

A note on the explicit vs. implicit interfaces
==============================================

Matplotlib has two interfaces. For an explanation of the trade-offs between the
explicit and implicit interfaces see :ref:`api_interfaces`.

In the explicit object-oriented (OO) interface we directly utilize instances of
:class:`axes.Axes` to build up the visualization in an instance of
:class:`figure.Figure`.  In the implicit interface, inspired by and modeled on
MATLAB, we use a global state-based interface which is encapsulated in the
:mod:`.pyplot` module to plot to the "current Axes".  See the :ref:`pyplot
tutorials <pyplot_tutorial>` for a more in-depth look at the
pyplot interface.

Most of the terms are straightforward but the main thing to remember
is that:

* The `.Figure` is the final image, and may contain one or more `~.axes.Axes`.
* The `~.axes.Axes` represents an individual plot (not to be confused with
   `~.axis.Axis`, which refers to the x-, y-, or z-axis of a plot).

We call methods that do the plotting directly from the Axes, which gives
us much more flexibility and power in customizing our plot.

.. note::

   In general, use the explicit interface over the implicit pyplot interface
   for plotting.

Our data
========

We'll use the data from the post from which this tutorial was derived.
It contains sales information for a number of companies.

.. GENERATED FROM PYTHON SOURCE LINES 58-76

.. code-block:: Python


    import matplotlib.pyplot as plt
    import numpy as np

    data = {'Barton LLC': 109438.50,
            'Frami, Hills and Schmidt': 103569.59,
            'Fritsch, Russel and Anderson': 112214.71,
            'Jerde-Hilpert': 112591.43,
            'Keeling LLC': 100934.30,
            'Koepp Ltd': 103660.54,
            'Kulas Inc': 137351.96,
            'Trantow-Barrows': 123381.38,
            'White-Trantow': 135841.99,
            'Will LLC': 104437.60}
    group_data = list(data.values())
    group_names = list(data.keys())
    group_mean = np.mean(group_data)








.. GENERATED FROM PYTHON SOURCE LINES 78-92

Getting started
===============

This data is naturally visualized as a barplot, with one bar per
group. To do this with the object-oriented approach, we first generate
an instance of :class:`figure.Figure` and
:class:`axes.Axes`. The Figure is like a canvas, and the Axes
is a part of that canvas on which we will make a particular visualization.

.. note::

   Figures can have multiple Axes on them. For information on how to do this,
   see the :ref:`Tight Layout tutorial
   <tight_layout_guide>`.

.. GENERATED FROM PYTHON SOURCE LINES 92-95

.. code-block:: Python


    fig, ax = plt.subplots()




.. image-sg:: /tutorials/images/sphx_glr_lifecycle_001.png
   :alt: lifecycle
   :srcset: /tutorials/images/sphx_glr_lifecycle_001.png, /tutorials/images/sphx_glr_lifecycle_001_2_00x.png 2.00x
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 96-97

Now that we have an Axes instance, we can plot on top of it.

.. GENERATED FROM PYTHON SOURCE LINES 97-101

.. code-block:: Python


    fig, ax = plt.subplots()
    ax.barh(group_names, group_data)




.. image-sg:: /tutorials/images/sphx_glr_lifecycle_002.png
   :alt: lifecycle
   :srcset: /tutorials/images/sphx_glr_lifecycle_002.png, /tutorials/images/sphx_glr_lifecycle_002_2_00x.png 2.00x
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 102-108

Controlling the style
=====================

There are many styles available in Matplotlib in order to let you tailor
your visualization to your needs. To see a list of styles, we can use
:mod:`.style`.

.. GENERATED FROM PYTHON SOURCE LINES 108-111

.. code-block:: Python


    print(plt.style.available)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    ['Solarize_Light2', '_classic_test_patch', '_mpl-gallery', '_mpl-gallery-nogrid', 'bmh', 'classic', 'dark_background', 'fast', 'fivethirtyeight', 'ggplot', 'grayscale', 'petroff10', 'seaborn-v0_8', 'seaborn-v0_8-bright', 'seaborn-v0_8-colorblind', 'seaborn-v0_8-dark', 'seaborn-v0_8-dark-palette', 'seaborn-v0_8-darkgrid', 'seaborn-v0_8-deep', 'seaborn-v0_8-muted', 'seaborn-v0_8-notebook', 'seaborn-v0_8-paper', 'seaborn-v0_8-pastel', 'seaborn-v0_8-poster', 'seaborn-v0_8-talk', 'seaborn-v0_8-ticks', 'seaborn-v0_8-white', 'seaborn-v0_8-whitegrid', 'tableau-colorblind10']




.. GENERATED FROM PYTHON SOURCE LINES 112-113

You can activate a style with the following:

.. GENERATED FROM PYTHON SOURCE LINES 113-116

.. code-block:: Python


    plt.style.use('fivethirtyeight')








.. GENERATED FROM PYTHON SOURCE LINES 117-118

Now let's remake the above plot to see how it looks:

.. GENERATED FROM PYTHON SOURCE LINES 118-122

.. code-block:: Python


    fig, ax = plt.subplots()
    ax.barh(group_names, group_data)




.. image-sg:: /tutorials/images/sphx_glr_lifecycle_003.png
   :alt: lifecycle
   :srcset: /tutorials/images/sphx_glr_lifecycle_003.png, /tutorials/images/sphx_glr_lifecycle_003_2_00x.png 2.00x
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 123-133

The style controls many things, such as color, linewidths, backgrounds,
etc.

Customizing the plot
====================

Now we've got a plot with the general look that we want, so let's fine-tune
it so that it's ready for print. First let's rotate the labels on the x-axis
so that they show up more clearly. We can gain access to these labels
with the :meth:`axes.Axes.get_xticklabels` method:

.. GENERATED FROM PYTHON SOURCE LINES 133-138

.. code-block:: Python


    fig, ax = plt.subplots()
    ax.barh(group_names, group_data)
    labels = ax.get_xticklabels()




.. image-sg:: /tutorials/images/sphx_glr_lifecycle_004.png
   :alt: lifecycle
   :srcset: /tutorials/images/sphx_glr_lifecycle_004.png, /tutorials/images/sphx_glr_lifecycle_004_2_00x.png 2.00x
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 139-142

If we'd like to set the property of many items at once, it's useful to use
the :func:`pyplot.setp` function. This will take a list (or many lists) of
Matplotlib objects, and attempt to set some style element of each one.

.. GENERATED FROM PYTHON SOURCE LINES 142-148

.. code-block:: Python


    fig, ax = plt.subplots()
    ax.barh(group_names, group_data)
    labels = ax.get_xticklabels()
    plt.setp(labels, rotation=45, horizontalalignment='right')




.. image-sg:: /tutorials/images/sphx_glr_lifecycle_005.png
   :alt: lifecycle
   :srcset: /tutorials/images/sphx_glr_lifecycle_005.png, /tutorials/images/sphx_glr_lifecycle_005_2_00x.png 2.00x
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 149-155

It looks like this cut off some of the labels on the bottom. We can
tell Matplotlib to automatically make room for elements in the figures
that we create. To do this we set the ``autolayout`` value of our
rcParams. For more information on controlling the style, layout, and
other features of plots with rcParams, see
:ref:`customizing`.

.. GENERATED FROM PYTHON SOURCE LINES 155-163

.. code-block:: Python


    plt.rcParams.update({'figure.autolayout': True})

    fig, ax = plt.subplots()
    ax.barh(group_names, group_data)
    labels = ax.get_xticklabels()
    plt.setp(labels, rotation=45, horizontalalignment='right')




.. image-sg:: /tutorials/images/sphx_glr_lifecycle_006.png
   :alt: lifecycle
   :srcset: /tutorials/images/sphx_glr_lifecycle_006.png, /tutorials/images/sphx_glr_lifecycle_006_2_00x.png 2.00x
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 164-167

Next, we add labels to the plot. To do this with the OO interface,
we can use the :meth:`.Artist.set` method to set properties of this
Axes object.

.. GENERATED FROM PYTHON SOURCE LINES 167-175

.. code-block:: Python


    fig, ax = plt.subplots()
    ax.barh(group_names, group_data)
    labels = ax.get_xticklabels()
    plt.setp(labels, rotation=45, horizontalalignment='right')
    ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
           title='Company Revenue')




.. image-sg:: /tutorials/images/sphx_glr_lifecycle_007.png
   :alt: Company Revenue
   :srcset: /tutorials/images/sphx_glr_lifecycle_007.png, /tutorials/images/sphx_glr_lifecycle_007_2_00x.png 2.00x
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 176-185

We can also adjust the size of this plot using the :func:`pyplot.subplots`
function. We can do this with the *figsize* keyword argument.

.. note::

   While indexing in NumPy follows the form (row, column), the *figsize*
   keyword argument follows the form (width, height). This follows
   conventions in visualization, which unfortunately are different from those
   of linear algebra.

.. GENERATED FROM PYTHON SOURCE LINES 185-193

.. code-block:: Python


    fig, ax = plt.subplots(figsize=(8, 4))
    ax.barh(group_names, group_data)
    labels = ax.get_xticklabels()
    plt.setp(labels, rotation=45, horizontalalignment='right')
    ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
           title='Company Revenue')




.. image-sg:: /tutorials/images/sphx_glr_lifecycle_008.png
   :alt: Company Revenue
   :srcset: /tutorials/images/sphx_glr_lifecycle_008.png, /tutorials/images/sphx_glr_lifecycle_008_2_00x.png 2.00x
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 194-203

For labels, we can specify custom formatting guidelines in the form of
functions. Below we define a function that takes an integer as input, and
returns a string as an output. When used with `.Axis.set_major_formatter` or
`.Axis.set_minor_formatter`, they will automatically create and use a
:class:`ticker.FuncFormatter` class.

For this function, the ``x`` argument is the original tick label and ``pos``
is the tick position.  We will only use ``x`` here but both arguments are
needed.

.. GENERATED FROM PYTHON SOURCE LINES 203-213

.. code-block:: Python



    def currency(x, pos):
        """The two arguments are the value and tick position"""
        if x >= 1e6:
            s = f'${x*1e-6:1.1f}M'
        else:
            s = f'${x*1e-3:1.0f}K'
        return s








.. GENERATED FROM PYTHON SOURCE LINES 214-217

We can then apply this function to the labels on our plot. To do this,
we use the ``xaxis`` attribute of our Axes. This lets you perform
actions on a specific axis on our plot.

.. GENERATED FROM PYTHON SOURCE LINES 217-227

.. code-block:: Python


    fig, ax = plt.subplots(figsize=(6, 8))
    ax.barh(group_names, group_data)
    labels = ax.get_xticklabels()
    plt.setp(labels, rotation=45, horizontalalignment='right')

    ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
           title='Company Revenue')
    ax.xaxis.set_major_formatter(currency)




.. image-sg:: /tutorials/images/sphx_glr_lifecycle_009.png
   :alt: Company Revenue
   :srcset: /tutorials/images/sphx_glr_lifecycle_009.png, /tutorials/images/sphx_glr_lifecycle_009_2_00x.png 2.00x
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 228-234

Combining multiple visualizations
=================================

It is possible to draw multiple plot elements on the same instance of
:class:`axes.Axes`. To do this we simply need to call another one of
the plot methods on that Axes object.

.. GENERATED FROM PYTHON SOURCE LINES 234-259

.. code-block:: Python


    fig, ax = plt.subplots(figsize=(8, 8))
    ax.barh(group_names, group_data)
    labels = ax.get_xticklabels()
    plt.setp(labels, rotation=45, horizontalalignment='right')

    # Add a vertical line, here we set the style in the function call
    ax.axvline(group_mean, ls='--', color='r')

    # Annotate new companies
    for group in [3, 5, 8]:
        ax.text(145000, group, "New Company", fontsize=10,
                verticalalignment="center")

    # Now we move our title up since it's getting a little cramped
    ax.title.set(y=1.05)

    ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
           title='Company Revenue')
    ax.xaxis.set_major_formatter(currency)
    ax.set_xticks([0, 25e3, 50e3, 75e3, 100e3, 125e3])
    fig.subplots_adjust(right=.1)

    plt.show()




.. image-sg:: /tutorials/images/sphx_glr_lifecycle_010.png
   :alt: Company Revenue
   :srcset: /tutorials/images/sphx_glr_lifecycle_010.png, /tutorials/images/sphx_glr_lifecycle_010_2_00x.png 2.00x
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 260-266

Saving our plot
===============

Now that we're happy with the outcome of our plot, we want to save it to
disk. There are many file formats we can save to in Matplotlib. To see
a list of available options, use:

.. GENERATED FROM PYTHON SOURCE LINES 266-269

.. code-block:: Python


    print(fig.canvas.get_supported_filetypes())





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    {'eps': 'Encapsulated Postscript', 'jpg': 'Joint Photographic Experts Group', 'jpeg': 'Joint Photographic Experts Group', 'pdf': 'Portable Document Format', 'pgf': 'PGF code for LaTeX', 'png': 'Portable Network Graphics', 'ps': 'Postscript', 'raw': 'Raw RGBA bitmap', 'rgba': 'Raw RGBA bitmap', 'svg': 'Scalable Vector Graphics', 'svgz': 'Scalable Vector Graphics', 'tif': 'Tagged Image File Format', 'tiff': 'Tagged Image File Format', 'webp': 'WebP Image Format'}




.. GENERATED FROM PYTHON SOURCE LINES 270-277

We can then use the :meth:`figure.Figure.savefig` in order to save the figure
to disk. Note that there are several useful flags we show below:

* ``transparent=True`` makes the background of the saved figure transparent
  if the format supports it.
* ``dpi=80`` controls the resolution (dots per square inch) of the output.
* ``bbox_inches="tight"`` fits the bounds of the figure to our plot.

.. GENERATED FROM PYTHON SOURCE LINES 277-280

.. code-block:: Python


    # Uncomment this line to save the figure.
    # fig.savefig('sales.png', transparent=False, dpi=80, bbox_inches="tight")








.. rst-class:: sphx-glr-timing

   **Total running time of the script:** (0 minutes 1.704 seconds)


.. _sphx_glr_download_tutorials_lifecycle.py:

.. only:: html

  .. container:: sphx-glr-footer sphx-glr-footer-example

    .. container:: sphx-glr-download sphx-glr-download-jupyter

      :download:`Download Jupyter notebook: lifecycle.ipynb <lifecycle.ipynb>`

    .. container:: sphx-glr-download sphx-glr-download-python

      :download:`Download Python source code: lifecycle.py <lifecycle.py>`

    .. container:: sphx-glr-download sphx-glr-download-zip

      :download:`Download zipped: lifecycle.zip <lifecycle.zip>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_
