Matplotlib 凡例のカスタマイズ

MatplotlibMatplotlibBeginner
今すぐ練習

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

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、Matplotlib で凡例を作成してカスタマイズする方法を探ります。凡例は、線、棒グラフ、マーカーなどのグラフ内の要素の意味を説明するために使用されます。特定の線、複雑なラベル、そしてより複雑なプロットに対する凡例の作成方法を示します。最後に、凡例をスタイリッシュにするためのカスタムクラスの書き方を紹介します。

VM のヒント

VM の起動が完了したら、左上隅をクリックして ノートブック タブに切り替え、Jupyter Notebook を使って練習しましょう。

時々、Jupyter Notebook が読み込み終了するまで数秒待つ必要がある場合があります。Jupyter Notebook の制限により、操作の検証を自動化することはできません。

学習中に問題に遭遇した場合は、Labby にお尋ねください。セッション後にフィードバックを提供してください。すぐに問題を解決いたします。

特定の線に対する凡例の作成

このステップでは、特定の線に対する凡例を作成します。

## 必要なライブラリをインポート
import matplotlib.pyplot as plt
import numpy as np

## グラフ用のデータを定義
t1 = np.arange(0.0, 2.0, 0.1)
t2 = np.arange(0.0, 2.0, 0.01)

## 複数の線を持つプロットを作成
fig, ax = plt.subplots()
l1, = ax.plot(t2, np.exp(-t2))
l2, l3 = ax.plot(t2, np.sin(2 * np.pi * t2), '--o', t1, np.log(1 + t1), '.')
l4, = ax.plot(t2, np.exp(-t2) * np.sin(2 * np.pi * t2),'s-.')

## 2つの線に対する凡例を作成
ax.legend((l2, l4), ('oscillatory', 'damped'), loc='upper right', shadow=True)

## グラフにラベルとタイトルを追加
ax.set_xlabel('time')
ax.set_ylabel('volts')
ax.set_title('Damped oscillation')

## グラフを表示
plt.show()

より複雑なラベルをプロットする

このステップでは、より複雑なラベルをプロットします。

## グラフ用のデータを定義
x = np.linspace(0, 1)

## 複数の線を持つグラフを作成
fig, (ax0, ax1) = plt.subplots(2, 1)
for n in range(1, 5):
    ax0.plot(x, x**n, label=f"{n=}")

## 複数列とタイトル付きの凡例を作成
leg = ax0.legend(loc="upper left", bbox_to_anchor=[0, 1],
                 ncols=2, shadow=True, title="Legend", fancybox=True)
leg.get_title().set_color("red")

## 複数の線とマーカーを持つグラフを作成
ax1.plot(x, x**2, label="multi\nline")
half_pi = np.linspace(0, np.pi / 2)
ax1.plot(np.sin(half_pi), np.cos(half_pi), label=r"$\frac{1}{2}\pi$")
ax1.plot(x, 2**(x**2), label="$2^{x^2}$")

## 影付きの凡例を作成
ax1.legend(shadow=True, fancybox=True)

## グラフを表示
plt.show()

より複雑なプロットに凡例を追加する

このステップでは、より複雑なプロットに凡例を追加します。

## グラフ用のデータを定義
fig, axs = plt.subplots(3, 1, layout="constrained")
top_ax, middle_ax, bottom_ax = axs

## 複数のバーを持つ棒グラフを作成
top_ax.bar([0, 1, 2], [0.2, 0.3, 0.1], width=0.4, label="Bar 1",
           align="center")
top_ax.bar([0.5, 1.5, 2.5], [0.3, 0.2, 0.2], color="red", width=0.4,
           label="Bar 2", align="center")
top_ax.legend()

## 複数のエラーを持つ誤差棒グラフを作成
middle_ax.errorbar([0, 1, 2], [2, 3, 1], xerr=0.4, fmt="s", label="test 1")
middle_ax.errorbar([0, 1, 2], [3, 2, 4], yerr=0.3, fmt="o", label="test 2")
middle_ax.errorbar([0, 1, 2], [1, 1, 3], xerr=0.4, yerr=0.3, fmt="^",
                   label="test 3")
middle_ax.legend()

## 凡例付きのステムチャートを作成
bottom_ax.stem([0.3, 1.5, 2.7], [1, 3.6, 2.7], label="stem test")
bottom_ax.legend()

## グラフを表示
plt.show()

1つ以上の凡例キーを持つ凡例エントリを作成する

このステップでは、1つ以上の凡例キーを持つ凡例エントリを作成します。

## グラフ用のデータを定義
fig, (ax1, ax2) = plt.subplots(2, 1, layout='constrained')
p1 = ax1.scatter([1], [5], c='r', marker='s', s=100)
p2 = ax1.scatter([3], [2], c='b', marker='o', s=100)
p3, = ax1.plot([1, 5], [4, 4],'m-d')

## 1つのエントリに2つのキーを持つ凡例を作成
l = ax1.legend([(p1, p3), p2], ['2つのキー', '1つのキー'], scatterpoints=1,
               numpoints=1, handler_map={tuple: HandlerTuple(ndivide=None)})

## 重ねて2つの棒グラフを作成し、凡例キー間のパディングを変更する
x_left = [1, 2, 3]
y_pos = [1, 3, 2]
y_neg = [2, 1, 4]
rneg = ax2.bar(x_left, y_neg, width=0.5, color='w', hatch='///', label='-1')
rpos = ax2.bar(x_left, y_pos, width=0.5, color='k', label='+1')

## 特定の`HandlerTuple`を使用して各凡例エントリを異なる方法で扱う
l = ax2.legend([(rpos, rneg), (rneg, rpos)], ['pad!=0', 'pad=0'],
               handler_map={(rpos, rneg): HandlerTuple(ndivide=None),
                            (rneg, rpos): HandlerTuple(ndivide=None, pad=0.)})

## グラフを表示
plt.show()

凡例を装飾するためのカスタムクラスを作成する

このステップでは、凡例を装飾するためのカスタムクラスを作成します。

## グラフ用のデータを定義
class HandlerDashedLines(HandlerLineCollection):
    """
    LineCollectionインスタンス用のカスタムハンドラ。
    """
    def create_artists(self, legend, orig_handle,
                       xdescent, ydescent, width, height, fontsize, trans):
        ## 何本の線があるかを調べる
        numlines = len(orig_handle.get_segments())
        xdata, xdata_marker = self.get_xdata(legend, xdescent, ydescent,
                                             width, height, fontsize)
        leglines = []
        ## 線が配置される垂直方向のスペースを
        ## 線の数に基づいて等しい部分に分割する
        ydata = np.full_like(xdata, height / (numlines + 1))
        ## 各線に対して、適切な位置に線を作成し
        ## 破線パターンを設定する
        for i in range(numlines):
            legline = Line2D(xdata, ydata * (numlines - i) - ydescent)
            self.update_prop(legline, orig_handle, legend)
            ## 色、破線パターン、および線幅を
            ## LineCollection内の線のそれに設定する
            try:
                color = orig_handle.get_colors()[i]
            except IndexError:
                color = orig_handle.get_colors()[0]
            try:
                dashes = orig_handle.get_dashes()[i]
            except IndexError:
                dashes = orig_handle.get_dashes()[0]
            try:
                lw = orig_handle.get_linewidths()[i]
            except IndexError:
                lw = orig_handle.get_linewidths()[0]
            if dashes[1] is not None:
                legline.set_dashes(dashes[1])
            legline.set_color(color)
            legline.set_transform(trans)
            legline.set_linewidth(lw)
            leglines.append(legline)
        return leglines

## 複数の線を持つグラフを作成
x = np.linspace(0, 5, 100)
fig, ax = plt.subplots()
colors = plt.rcParams['axes.prop_cycle'].by_key()['color'][:5]
styles = ['solid', 'dashed', 'dashed', 'dashed','solid']
for i, color, style in zip(range(5), colors, styles):
    ax.plot(x, np.sin(x) -.1 * i, c=color, ls=style)

## プロキシアーティストと凡例を作成
line = [[(0, 0)]]
lc = mcol.LineCollection(5 * line, linestyles=styles, colors=colors)
ax.legend([lc], ['multi-line'], handler_map={type(lc): HandlerDashedLines()},
          handlelength=2.5, handleheight=3)

## グラフを表示
plt.show()

まとめ

この実験では、Matplotlibで凡例を作成してカスタマイズする方法を学びました。特定の線、複雑なラベル、およびより複雑なプロットに対する凡例の作成方法を示しました。また、凡例を装飾するためのカスタムクラスを作成する方法も示しました。凡例は、あらゆるグラフの重要な部分であり、それらを作成してカスタマイズする方法を理解することは、効果的なビジュアライゼーションを作成するために不可欠です。