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

.. only:: html

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

        Click :ref:`here <sphx_glr_download_gallery_statistics_barchart_demo.py>`
        to download the full example code

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

.. _sphx_glr_gallery_statistics_barchart_demo.py:


===================================
Percentiles as horizontal bar chart
===================================

Bar charts are useful for visualizing counts, or summary statistics
with error bars. Also see the :doc:`/gallery/lines_bars_and_markers/barchart`
or the :doc:`/gallery/lines_bars_and_markers/barh` example for simpler versions
of those features.

This example comes from an application in which grade school gym
teachers wanted to be able to show parents how their child did across
a handful of fitness tests, and importantly, relative to how other
children did. To extract the plotting code for demo purposes, we'll
just make up some data for little Johnny Doe.

.. GENERATED FROM PYTHON SOURCE LINES 17-102

.. code-block:: default


    from collections import namedtuple
    import numpy as np
    import matplotlib.pyplot as plt


    Student = namedtuple('Student', ['name', 'grade', 'gender'])
    Score = namedtuple('Score', ['value', 'unit', 'percentile'])


    def to_ordinal(num):
        """Convert an integer to an ordinal string, e.g. 2 -> '2nd'."""
        suffixes = {str(i): v
                    for i, v in enumerate(['th', 'st', 'nd', 'rd', 'th',
                                           'th', 'th', 'th', 'th', 'th'])}
        v = str(num)
        # special case early teens
        if v in {'11', '12', '13'}:
            return v + 'th'
        return v + suffixes[v[-1]]


    def format_score(score):
        """
        Create score labels for the right y-axis as the test name followed by the
        measurement unit (if any), split over two lines.
        """
        return f'{score.value}\n{score.unit}' if score.unit else str(score.value)


    def plot_student_results(student, scores_by_test, cohort_size):
        fig, ax1 = plt.subplots(figsize=(9, 7), constrained_layout=True)
        fig.canvas.manager.set_window_title('Eldorado K-8 Fitness Chart')

        ax1.set_title(student.name)
        ax1.set_xlabel(
            'Percentile Ranking Across {grade} Grade {gender}s\n'
            'Cohort Size: {cohort_size}'.format(
                grade=to_ordinal(student.grade),
                gender=student.gender.title(),
                cohort_size=cohort_size))

        test_names = list(scores_by_test.keys())
        percentiles = [score.percentile for score in scores_by_test.values()]

        rects = ax1.barh(test_names, percentiles, align='center', height=0.5)
        # Partition the percentile values to be able to draw large numbers in
        # white within the bar, and small numbers in black outside the bar.
        large_percentiles = [to_ordinal(p) if p > 40 else '' for p in percentiles]
        small_percentiles = [to_ordinal(p) if p <= 40 else '' for p in percentiles]
        ax1.bar_label(rects, small_percentiles,
                      padding=5, color='black', fontweight='bold')
        ax1.bar_label(rects, large_percentiles,
                      padding=-32, color='white', fontweight='bold')

        ax1.set_xlim([0, 100])
        ax1.set_xticks([0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100])
        ax1.xaxis.grid(True, linestyle='--', which='major',
                       color='grey', alpha=.25)
        ax1.axvline(50, color='grey', alpha=0.25)  # median position

        # Set the right-hand Y-axis ticks and labels
        ax2 = ax1.twinx()
        # Set equal limits on both yaxis so that the ticks line up
        ax2.set_ylim(ax1.get_ylim())
        # Set the tick locations and labels
        ax2.set_yticks(
            np.arange(len(scores_by_test)),
            labels=[format_score(score) for score in scores_by_test.values()])

        ax2.set_ylabel('Test Scores')


    student = Student(name='Johnny Doe', grade=2, gender='Boy')
    scores_by_test = {
        'Pacer Test': Score(7, 'laps', percentile=37),
        'Flexed Arm\n Hang': Score(48, 'sec', percentile=95),
        'Mile Run': Score('12:52', 'min:sec', percentile=73),
        'Agility': Score(17, 'sec', percentile=60),
        'Push Ups': Score(14, '', percentile=16),
    }

    plot_student_results(student, scores_by_test, cohort_size=62)
    plt.show()




.. image-sg:: /gallery/statistics/images/sphx_glr_barchart_demo_001.png
   :alt: Johnny Doe
   :srcset: /gallery/statistics/images/sphx_glr_barchart_demo_001.png, /gallery/statistics/images/sphx_glr_barchart_demo_001_2_0x.png 2.0x
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 103-111

.. admonition:: References

   The use of the following functions, methods, classes and modules is shown
   in this example:

   - `matplotlib.axes.Axes.bar` / `matplotlib.pyplot.bar`
   - `matplotlib.axes.Axes.bar_label` / `matplotlib.pyplot.bar_label`
   - `matplotlib.axes.Axes.twinx` / `matplotlib.pyplot.twinx`


.. _sphx_glr_download_gallery_statistics_barchart_demo.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: barchart_demo.py <barchart_demo.py>`



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

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


.. only:: html

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

    Keywords: matplotlib code example, codex, python plot, pyplot
    `Gallery generated by Sphinx-Gallery
    <https://sphinx-gallery.readthedocs.io>`_
