Phần 14: Trục đôi – Matplotib Basic

Phần 14: Trục đôi                        – Matplotib Basic

1. Khái niệm :

Trục đôi được xem là có ích khi có trục x hay y kép trong 1 hình. Ngoài ra, khi vẽ những đường cong với những đơn vị khác nhau v. Matplotlib hỗ trợ bằng hàm twinx và twiny.
Trong ví dụ sau, biểu đồ có trục y kép, 1 trục hiển thị exp (x) và trục kia hiển thị log (x) –
import matplotlib.pyplot as plt
import numpy as np
fig = plt.determine()
a1 = fig.add_axes([0,0,1,1])
x = np.arange(1,11)
a1.plot(x,np.exp(x))
a1.set_ylabel('exp')
a2 = a1.twinx()
a2.plot(x, np.log(x),'ro-')
a2.set_ylabel('log')
fig.legend(labels = ('exp','log'),loc='higher left')
plt.present()

2. Ví dụ :

Ví dụ 1 : Các tỷ lệ khác nhau trên cùng 1 trục
Demo cách hiển thị 2 thang đo trên trục y bên trái và bên phải.
Ví dụ này sử dụng thang đo độ F và độ C.
import matplotlib.pyplot as plt
import numpy as np


def fahrenheit2celsius(temp):
    """
    Returns temperature in Celsius.
    """
    return (5. / 9.) * (temp - 32)


def convert_ax_c_to_celsius(ax_f):
    """
    Update second axis in accordance with first axis.
    """
    y1, y2 = ax_f.get_ylim()
    ax_c.set_ylim(fahrenheit2celsius(y1), fahrenheit2celsius(y2))
    ax_c.determine.canvas.draw()

fig, ax_f = plt.subplots()
ax_c = ax_f.twinx()

# mechanically replace ylim of ax2 when ylim of ax1 modifications.
ax_f.callbacks.join("ylim_changed", convert_ax_c_to_celsius)
ax_f.plot(np.linspace(-40, 120, 100))
ax_f.set_xlim(0, 100)

ax_f.set_title('Two scales: Fahrenheit and Celsius')
ax_f.set_ylabel('Fahrenheit')
ax_c.set_ylabel('Celsius')

plt.present()
Ví dụ 2 : Các plot với những tỷ lệ khác nhau
Hai plot trên cùng 1 trục với tỷ lệ bên trái và bên phải khác nhau.
Bí quyết là sử dụng 2 trục khác nhau có cùng trục x. Bạn sẽ có thể sử dụng những bộ định dạng và bộ định vị matplotlib.ticker riêng biệt vì 2 trục là độc lập.
Các trục như thế được tạo nên bằng việc gọi phương thức Axes.twinx (). Giống nhau như thế, Axes.twiny () có sẵn để tạo nên các trục có chung trục y nhưng có tỷ lệ trên và dưới khác nhau.
import numpy as np
import matplotlib.pyplot as plt

# Create some mock information
t = np.arange(0.01, 10.0, 0.01)
data1 = np.exp(t)
data2 = np.sin(2 * np.pi * t)

fig, ax1 = plt.subplots()

shade = 'tab:purple'
ax1.set_xlabel('time (s)')
ax1.set_ylabel('exp', shade=shade)
ax1.plot(t, data1, shade=shade)
ax1.tick_params(axis='y', labelcolor=shade)

ax2 = ax1.twinx()  # instantiate a second axes that shares the identical x-axis

shade = 'tab:blue'
ax2.set_ylabel('sin', shade=shade)  # we already dealt with the x-label with ax1
ax2.plot(t, data2, shade=shade)
ax2.tick_params(axis='y', labelcolor=shade)

fig.tight_layout()  # in any other case the suitable y-label is barely clipped
plt.present()
Ví dụ 3 : Phần trăm dưới dạng biểu đồ thanh ngang
Biểu đồ thanh rất có ích để hiển thị số lượng hay thống kê tóm tắt với những thanh lỗi. Ngoài ra, xem biểu đồ thanh được nhóm có label hay ví dụ về biểu đồ thanh ngang để biết những phiên bản đơn giản hơn của các tính năng đó.
Ví dụ này xuất phát từ 1 ứng dụng trong đó giáo viên thể dục của lớp muốn có thể cho phụ huynh thấy con họ đã làm thế nào qua những bài kiểm tra thể lực và quan trọng là liên quan tới cách những đứa trẻ khác đã làm. Để trích xuất cho mục đích demo, ta sẽ chỉ tạo những dữ liệu nhỏ.
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator
from collections import namedtuple

np.random.seed(42)

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

# GLOBAL CONSTANTS
testNames = ['Pacer Test', 'Flexed Armn Hang', 'Mile Run', 'Agility',
             'Push Ups']
testMeta = dict(zip(testNames, ['laps', 'sec', 'min:sec', 'sec', '']))


def attach_ordinal(num):
    """helper operate so as to add ordinal string to integers

    1 -&gt 1st
    56 -&gt 56th
    """
    suffixes = {str(i): v
                for i, v in enumerate(['th', 'st', 'nd', 'rd', 'th',
                                       'th', 'th', 'th', 'th', 'th'])}

    v = str(num)
    # particular case early teenagers
    if v in {'11', '12', '13'}:
        return v + 'th'
    return v + suffixes[v[-1]]


def format_score(scr, check):
    """
    Build up the rating labels for the suitable Y-axis by first
    appending a carriage return to every string after which tacking on
    the suitable meta info (i.e., 'laps' vs 'seconds'). We
    need the labels centered on the ticks, so if there isn't any meta
    data (like for pushups) then do not add the carriage return to
    the string
    """
    md = testMeta[test]
    if md:
        return '{0}n{1}'.format(scr, md)
    else:
        return scr


def format_ycursor(y):
    y = int(y)
    if y &lt 0 or y &gt= len(testNames):
        return ''
    else:
        return testNames[y]


def plot_student_results(scholar, scores, cohort_size):
    #  create the determine
    fig, ax1 = plt.subplots(figsize=(9, 7))
    fig.subplots_adjust(left=0.115, proper=0.88)
    fig.canvas.set_window_title('Eldorado Ok-8 Fitness Chart')

    pos = np.arange(len(testNames))

    rects = ax1.barh(pos, [scores[k].percentile for okay in testNames],
                     align='middle',
                     peak=0.5,
                     tick_label=testNames)

    ax1.set_title(scholar.identify)

    ax1.set_xlim([0, 100])
    ax1.xaxis.set_major_locator(MaxNLocator(11))
    ax1.xaxis.grid(True, linestyle='--', which='main',
                   shade='gray', alpha=.25)

    # Plot a stable vertical gridline to focus on the median place
    ax1.axvline(50, shade='gray', alpha=0.25)

    # Set the suitable-hand Y-axis ticks and labels
    ax2 = ax1.twinx()

    scoreLabels = [format_score(scores[k].rating, okay) for okay in testNames]

    # set the tick places
    ax2.set_yticks(pos)
    # ensure that the bounds are set equally on each yaxis so the
    # ticks line up
    ax2.set_ylim(ax1.get_ylim())

    # set the tick labels
    ax2.set_yticklabels(scoreLabels)

    ax2.set_ylabel('Test Scores')

    xlabel = ('Percentile Ranking Across {grade} Grade {gender}sn'
              'Cohort Size: {cohort_size}')
    ax1.set_xlabel(xlabel.format(grade=attach_ordinal(scholar.grade),
                                 gender=scholar.gender.title(),
                                 cohort_size=cohort_size))

    rect_labels = []
    # Lastly, write within the rating inside every bar to assist in interpretation
    for rect in rects:
        # Rectangle widths are already integer-valued however are floating
        # sort, so it helps to take away the trailing decimal level and 0 by
        # changing width to int sort
        width = int(rect.get_width())

        rankStr = attach_ordinal(width)
        # The bars aren't vast sufficient to print the rating inside
        if width &lt 40:
            # Shift the textual content to the suitable facet of the suitable edge
            xloc = 5
            # Black towards white background
            clr = 'black'
            align = 'left'
        else:
            # Shift the textual content to the left facet of the suitable edge
            xloc = -5
            # White on magenta
            clr = 'white'
            align = 'proper'

        # Center the textual content vertically within the bar
        yloc = rect.get_y() + rect.get_height() / 2
        label = ax1.annotate(rankStr, xy=(width, yloc), xytext=(xloc, 0),
                            textcoords="offset factors",
                            ha=align, va='middle',
                            shade=clr, weight='daring', clip_on=True)
        rect_labels.append(label)

    # make the interactive mouse over give the bar title
    ax2.fmt_ydata = format_ycursor
    # return the entire artists created
    return {'fig': fig,
            'ax': ax1,
            'ax_right': ax2,
            'bars': rects,
            'perc_labels': rect_labels}


scholar = Student('Johnny Doe', 2, 'boy')
scores = dict(zip(testNames,
                  (Score(v, p) for v, p in
                   zip(['7', '48', '12:52', '17', '14'],
                       np.spherical(np.random.uniform(0, 1,
                                                  len(testNames)) * 100, 0)))))
cohort_size = 62  # The variety of different 2nd grade boys

arts = plot_student_results(scholar, scores, cohort_size)
plt.present()

admin

Leave a Reply

Your email address will not be published. Required fields are marked *