.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "tutorials/introductory/lifecycle.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note Click :ref:`here ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_tutorials_introductory_lifecycle.py: ======================= 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 `_ by Chris Moffitt. It was transformed into this tutorial by Chris Holdgraf. A note on the Object-Oriented API vs. Pyplot ============================================ Matplotlib has two interfaces. The first is an object-oriented (OO) interface. In this case, we utilize an instance of :class:`axes.Axes` in order to render visualizations on an instance of :class:`figure.Figure`. The second is based on MATLAB and uses a state-based interface. This is encapsulated in the :mod:`.pyplot` module. See the :doc:`pyplot tutorials ` 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 that may contain 1 or more Axes. * The Axes represent an individual plot (don't confuse this with the word "axis", which refers to the x/y 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, try to use the object-oriented interface over the pyplot interface. 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 52-71 .. code-block:: default import numpy as np import matplotlib.pyplot as plt 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 73-87 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 :doc:`Tight Layout tutorial `. .. GENERATED FROM PYTHON SOURCE LINES 87-90 .. code-block:: default fig, ax = plt.subplots() .. image:: /tutorials/introductory/images/sphx_glr_lifecycle_001.png :alt: lifecycle :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 91-92 Now that we have an Axes instance, we can plot on top of it. .. GENERATED FROM PYTHON SOURCE LINES 92-96 .. code-block:: default fig, ax = plt.subplots() ax.barh(group_names, group_data) .. image:: /tutorials/introductory/images/sphx_glr_lifecycle_002.png :alt: lifecycle :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out Out: .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 97-103 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 103-106 .. code-block:: default print(plt.style.available) .. rst-class:: sphx-glr-script-out Out: .. code-block:: none ['Solarize_Light2', '_classic_test_patch', 'bmh', 'classic', 'dark_background', 'fast', 'fivethirtyeight', 'ggplot', 'grayscale', 'seaborn', 'seaborn-bright', 'seaborn-colorblind', 'seaborn-dark', 'seaborn-dark-palette', 'seaborn-darkgrid', 'seaborn-deep', 'seaborn-muted', 'seaborn-notebook', 'seaborn-paper', 'seaborn-pastel', 'seaborn-poster', 'seaborn-talk', 'seaborn-ticks', 'seaborn-white', 'seaborn-whitegrid', 'tableau-colorblind10'] .. GENERATED FROM PYTHON SOURCE LINES 107-108 You can activate a style with the following: .. GENERATED FROM PYTHON SOURCE LINES 108-111 .. code-block:: default plt.style.use('fivethirtyeight') .. GENERATED FROM PYTHON SOURCE LINES 112-113 Now let's remake the above plot to see how it looks: .. GENERATED FROM PYTHON SOURCE LINES 113-117 .. code-block:: default fig, ax = plt.subplots() ax.barh(group_names, group_data) .. image:: /tutorials/introductory/images/sphx_glr_lifecycle_003.png :alt: lifecycle :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out Out: .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 118-128 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 128-133 .. code-block:: default fig, ax = plt.subplots() ax.barh(group_names, group_data) labels = ax.get_xticklabels() .. image:: /tutorials/introductory/images/sphx_glr_lifecycle_004.png :alt: lifecycle :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 134-137 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 137-143 .. code-block:: default fig, ax = plt.subplots() ax.barh(group_names, group_data) labels = ax.get_xticklabels() plt.setp(labels, rotation=45, horizontalalignment='right') .. image:: /tutorials/introductory/images/sphx_glr_lifecycle_005.png :alt: lifecycle :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out Out: .. code-block:: none [None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None] .. GENERATED FROM PYTHON SOURCE LINES 144-150 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 :doc:`/tutorials/introductory/customizing`. .. GENERATED FROM PYTHON SOURCE LINES 150-158 .. code-block:: default 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:: /tutorials/introductory/images/sphx_glr_lifecycle_006.png :alt: lifecycle :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out Out: .. code-block:: none [None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None] .. GENERATED FROM PYTHON SOURCE LINES 159-162 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 162-170 .. code-block:: default 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:: /tutorials/introductory/images/sphx_glr_lifecycle_007.png :alt: Company Revenue :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out Out: .. code-block:: none [(-10000.0, 140000.0), Text(0.5, 44.08838834764833, 'Total Revenue'), Text(43.999999999999986, 0.5, 'Company'), Text(0.5, 1.0, 'Company Revenue')] .. GENERATED FROM PYTHON SOURCE LINES 171-180 We can also adjust the size of this plot using the :func:`pyplot.subplots` function. We can do this with the ``figsize`` kwarg. .. note:: While indexing in NumPy follows the form (row, column), the figsize kwarg follows the form (width, height). This follows conventions in visualization, which unfortunately are different from those of linear algebra. .. GENERATED FROM PYTHON SOURCE LINES 180-188 .. code-block:: default 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:: /tutorials/introductory/images/sphx_glr_lifecycle_008.png :alt: Company Revenue :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out Out: .. code-block:: none [(-10000.0, 140000.0), Text(0.5, 43.823223304703376, 'Total Revenue'), Text(43.999999999999986, 0.5, 'Company'), Text(0.5, 1.0, 'Company Revenue')] .. GENERATED FROM PYTHON SOURCE LINES 189-198 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 198-208 .. code-block:: default def currency(x, pos): """The two args are the value and tick position""" if x >= 1e6: s = '${:1.1f}M'.format(x*1e-6) else: s = '${:1.0f}K'.format(x*1e-3) return s .. GENERATED FROM PYTHON SOURCE LINES 209-212 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 212-222 .. code-block:: default 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:: /tutorials/introductory/images/sphx_glr_lifecycle_009.png :alt: Company Revenue :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 223-229 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 229-254 .. code-block:: default 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:: /tutorials/introductory/images/sphx_glr_lifecycle_010.png :alt: Company Revenue :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 255-261 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 261-264 .. code-block:: default print(fig.canvas.get_supported_filetypes()) .. rst-class:: sphx-glr-script-out 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'} .. GENERATED FROM PYTHON SOURCE LINES 265-272 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 272-275 .. code-block:: default # 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 3.396 seconds) .. _sphx_glr_download_tutorials_introductory_lifecycle.py: .. only :: html .. container:: sphx-glr-footer :class: sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: lifecycle.py ` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: lifecycle.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature Keywords: matplotlib code example, codex, python plot, pyplot `Gallery generated by Sphinx-Gallery `_