Создание горизонтальной столбчатой диаграммы процентилей

Beginner

This tutorial is from open-source community. Access the source code

Введение

В этом практическом занятии мы научимся создавать горизонтальную столбчатую диаграмму с использованием библиотеки Matplotlib на Python. Мы рассмотрим пример, когда учителя физкультуры хотят показать родителям, как их ребенок справился с несколькими тестами на физическую подготовку по сравнению с другими детьми. Для демонстрации кода построения графиков мы придумаем некоторые данные для малыша Джони Доу.

Советы по виртуальной машине

После запуска виртуальной машины нажмите в левом верхнем углу, чтобы переключиться на вкладку Notebook и получить доступ к Jupyter Notebook для практики.

Иногда вам может потребоваться подождать несколько секунд, пока Jupyter Notebook загрузится. Проверка операций не может быть автоматизирована из-за ограничений Jupyter Notebook.

Если у вас возникнут проблемы во время обучения, не стесняйтесь обращаться к Labby. После занятия оставьте отзыв, и мы оперативно решим проблему для вас.

Импорт библиотек

Мы начинаем с импорта необходимых библиотек. Мы будем использовать numpy для создания наших данных и matplotlib.pyplot для построения графика.

import matplotlib.pyplot as plt
import numpy as np

Определение данных

Мы определяем наши данные с использованием именованных кортежей (named tuples). Мы определяем кортеж Student с именем студента, классом и полом. Также мы определяем кортеж Score со значением оценки, единицей измерения и процентилем.

from collections import namedtuple

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

Определение вспомогательных функций

Мы определяем две вспомогательные функции. Первая функция, to_ordinal, преобразует целое число в порядковое числительное в виде строки (например, 2 -> '2nd'). Вторая функция, format_score, создает метки для правой оси y в виде названия теста, за которым следует единица измерения (если она есть), разделенные на две строки.

def to_ordinal(num):
    suffixes = {str(i): v
                for i, v in enumerate(['th', 'st', 'nd', 'rd', 'th',
                                       'th', 'th', 'th', 'th', 'th'])}
    v = str(num)
    if v in {'11', '12', '13'}:
        return v + 'th'
    return v + suffixes[v[-1]]

def format_score(score):
    return f'{score.value}\n{score.unit}' if score.unit else str(score.value)

Определение функции построения графика

Мы определяем функцию с именем plot_student_results, которая принимает кортеж Student, словарь с оценками по тестам и размер когорты. Эта функция создает горизонтальную столбчатую диаграмму процентного ранжирования для каждого теста по сравнению с когортой учеников того же класса и пола.

def plot_student_results(student, scores_by_test, cohort_size):
    fig, ax1 = plt.subplots(figsize=(9, 7), layout='constrained')
    fig.canvas.manager.set_window_title('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)

    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)

    ax2 = ax1.twinx()
    ax2.set_ylim(ax1.get_ylim())
    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')

Определение данных для графика

Мы определяем данные для графика с использованием именованных кортежей (named tuples), которые мы определили ранее. Мы создаем кортеж Student для Джони Доу и словарь кортежей Score для каждого теста.

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, передав в качестве аргументов данные о студенте, оценки по тестам и размер когорты. Затем мы вызываем plt.show() для отображения графика.

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

Резюме

В этом практическом занятии (lab) мы научились создавать горизонтальную столбчатую диаграмму с использованием библиотеки Matplotlib в Python. Мы использовали пример, когда учителя физкультуры хотят показать родителям, как их ребенок справился с несколькими тестами на физическую подготовку по сравнению с другими детьми. Мы определили наши данные с использованием именованных кортежей (named tuples) и вспомогательные функции для преобразования целых чисел в порядковые числительные в виде строк и создания меток для правой оси y. Мы определили функцию построения графика, которая создает горизонтальную столбчатую диаграмму процентного ранжирования для каждого теста по сравнению с когортой учеников того же класса и пола. Затем мы вызвали функцию построения графика с нашими данными и отобразили график.