Skip to content

Matplotlibでプロットの外に凡例を配置する方法

Updated on

データ可視化において凡例の位置を管理することは、しばしば課題となることがあります。今日は、Matplotlibを使用してプロット領域の外に凡例を効果的に配置する方法を、具体的な例とステップバイステップの手順で説明します。凡例がデータに干渉しないようにしましょう!

問題の理解

プロットの凡例は、データ解釈に欠かせない要素でありながら、プロットスペースを占有することがあり、詰まった、読みにくいプロットを引き起こす可能性があります。この問題の解決策として、凡例をプロット領域の外に移動する方法があります。

Matplotlibの解決策

データ可視化のための堅牢で多機能なPythonライブラリであるMatplotlibは、プロットの外に凡例を配置するための簡単な解決策を提供しています。

このコンセプトを説明するために、Matplotlibのpyplot APIを使用して単純な折れ線グラフを作成しましょう:

import matplotlib.pyplot as plt
import numpy as np
 
x = np.linspace(0, 10, 100)
 
plt.plot(x, np.sin(x), label='sin(x)')
plt.plot(x, np.cos(x), label='cos(x)')
plt.legend()
plt.show()

上記のコードでは、sin(x)cos(x)を表す2つの折れ線グラフがあります。legend()関数呼び出しは、プロット領域内に凡例を追加し、データの一部を隠してしまうことがあります。

プロットの外に凡例を配置する方法

凡例をプロットの外に移動するには、legend()関数のbbox_to_anchorパラメータを使用することができます。このパラメータを使用すると、凡例の境界ボックスの位置をプロットの軸に対して指定できます。

次の例では、凡例をプロットの右側に配置しています。

plt.plot(x, np.sin(x), label='sin(x)')
plt.plot(x, np.cos(x), label='cos(x)')
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()

このコードでは、bbox_to_anchor=(1.05, 1)は、凡例の境界ボックスを軸の外、左上隅に配置します。loc='upper left'は、bbox_to_anchorで指定された座標に置かれるべき凡例ボックス内の点を指定します。

凡例の調整

基本的な配置以外にも、凡例をカスタマイズして必要に応じて調整することができます。

フォントサイズを減らす

凡例テキストのフォントサイズを小さくするには:

plt.plot(x, np.sin(x), label='sin(x)')
plt.plot(x, np.cos(x), label='cos(x)')
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', prop={'size': 6})
plt.show()

このコードでは prop={'size': 6} が使われて、凡例テキストのフォントサイズが小さくなり、凡例ボックス全体も小さくなります。

凡例の方向を変更する

水平方向に凡例を表示する場合は、 ncol パラメータを使用して列数を指定します。

plt.plot(x, np.sin(x), label='sin(x)')
plt.plot(x, np.cos(x), label='cos(x)')
plt.legend(bbox_to_anchor=(0.5, -0.15), loc='upper center', ncol=2)
plt.show()

Matplotlib凡例の位置の制御

Pythonによるデータ可視化で頻繁に行われるタスクの1つは、明確で簡潔で魅力的なプロットを作成することです。そのためには、Matplotlibでプロット外に凡例を適切に配置することが重要です。この包括的なガイドでは、様々な方法を紹介しながら、Matplotlibの凡例を最適な位置に配置する方法を解説します。

bbox_to_anchor:より良い凡例の位置のための重要な機能

Matplotlibプロットのボックス外に凡例を配置するための多数の手法がありますが、最も柔軟かつ効率的な方法の1つは、 bbox_to_anchor キーワード引数を使用することです。この強力な機能を活用して、プロットの美しさを向上させる方法について深く理解していきましょう。

bbox_to_anchor の基本的な応用例として、以下の例を考えてみます。ここでは、凡例を軸境界の外側に少し移動させます。

import matplotlib.pyplot as plt
import numpy as np
 
x = np.arange(10)
 
fig = plt.figure()
ax = plt.subplot(111)
 
for i in range(5):
    ax.plot(x, i * x, label='$y = %ix$' % i)
 
ax.legend(bbox_to_anchor=(1.1, 1.05))
 
plt.show()

上記のコードスニペットでは、凡例は軸境界の右上隅からわずかに右上に配置され、プロットを遮らずに簡単に見やすくなっています。

Shrinkのパワーを開放する:最適な凡例の位置を決定するためのキーとなる別の手段

プロットよりもさらに外側に凡例を移動させたい場合は、現在のプロットの寸法を縮小することを考えてみることができます。下のコード例を見てみましょう。

import matplotlib.pyplot as plt
import numpy as np
 
x = np.arange(10)
 
fig = plt.figure()
ax = plt.subplot(111)
 
for i in range(5):
    ax.plot(x, i * x, label='$y = %ix$'%i)
 
# 現在の軸を20%縮小する
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
 
# 現在の軸の右に凡例を配置する
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
 
plt.show()

この手法を使うことで、プロットスペースの一部を快適に凡例に割り当てることができます。ax.get_position()を使用して現在の軸の位置を取得し、それを調整してから凡例を再配置する方法に注意してください。

プロットの下に凡例を配置する

プロットの右側に凡例を配置することが適切でない場合は、プロットの下に配置するオプションもあります。以下は例です。

import matplotlib.pyplot as plt
import numpy as np
 
x = np.arange(10)
 
fig = plt.figure()
ax = plt.subplot(111)
 
for i in range(5):
    line, = ax.plot(x, i * x, label='$y = %ix$'%i)
 
# 現在の軸の高さを下部分に10%縮小する
box = ax.get_position()
ax.set_position([box.x0, box.y0 + box.height * 0.1,
                 box.width, box.height * 0.9])
 
# 現在の軸の下に凡例を配置する
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05),
          fancybox=True, shadow=True, ncol=5)
 
plt.show()

この手法により、利用可能なスペースを効果的に活用してプロットの視認性を妨げずに凡例を表示できるようになります。

The Legend of Legends: Matplotlib Legend Guide

データサイエンティストの新人であろうと経験豊富なプロフェッショナルであろうと、Matplotlibプロットで凡例の配置を制御する方法を知っておくことは重要なスキルです。これまでプロットの外部に凡例を配置するためのいくつかの方法を扱ってきましたが、いくつかの高度なカスタマイズについて掘り下げてみましょう。

凡例スタイルの調整

ときには、凡例をより読みやすく、美しくすることが必要になります。fancyboxshadowborderpadパラメータを使用すると、多様なスタイリングオプションが可能になります。

ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05), 
          fancybox=True, shadow=True, borderpad=1)

これらのパラメータを適切に設定することで、凡例の周りにいくつかの余白や影を追加することができます。

凡例の線幅とフォントサイズの調整

凡例の線幅とフォントサイズを調整することもできます。以下は例です。

# 凡例の線幅とフォントサイズを調整する
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05),
          fontsize=12, frameon=False, handlelength=2,
          handletextpad=1, borderaxespad=2)

これにより、凡例のテキストや線幅の比率を調整できます。

カスタム凡例テキストの使用

プロットに複数のデータシリーズがある場合、デフォルトの凡例テキストが良くない場合があります。例えば、シリーズに独自のカラーマップがある場合、それを凡例に反映させる必要があります。以下は、matplotlib.patches.Patchを使用してカスタムテキストを凡例に追加する例です。

import matplotlib.patches as mpatches
 
# カスタム凡例テキストを使用するために、patchesを使う
patch1 = mpatches.Patch(color='blue', label='Line 1')
patch2 = mpatches.Patch(color='orange', label='Line 2')
ax.legend(handles=[patch1, patch2], loc='lower right')

これにより、Line 1Line 2のテキストがカスタムカラーで凡例内に表示されます。

複数の凡例を追加する

最後に、複数のデータシリーズを表示し、それぞれに凡例を追加する場合を考えます。ここでは、ax.add_artistを使用して複数の凡例を処理します。以下は例です。

import matplotlib.lines as mlines
 
# 複数の凡例を1つのグラフに追加する
blue_line = mlines.Line2D([], [], color='blue', linewidth=2,
                          label='Line 1')
orange_line = mlines.Line2D([], [], color='orange', linewidth=2,
                            label='Line 2')
green_patch = mpatches.Patch(color='green', label='Line 3')
red_patch = mpatches.Patch(color='red', label='Line 4')
ax.add_artist(ax.legend(handles=[blue_line, orange_line], loc='upper left'))
ax.add_artist(ax.legend(handles=[green_patch, red_patch], loc='lower right'))

これにより、2つの独立した凡例がプロットに追加され、プロットを読みやすく簡潔にすることができます。

この例では、 fancybox=True は凡例のボックスに円角を付け、 shadow=True は影効果を追加し、 borderpad=1.5 はボックス内の余白を増やします。

凡例エントリの並べ替え

場合によっては、凡例のエントリの順序を変更したい場合があります。Matplotlibの HandlerLine2D クラスを使用すると、これを実現できます。以下は簡単な例です:

from matplotlib.lines import Line2D
 
fig, ax = plt.subplots()
lines = []
labels = []
 
for i in range(5):
    line, = ax.plot(x, i * x, label='$y = %ix$' % i)
    lines.append(line)
    labels.append('$y = %ix$' % i)
 
# ラベルとラインハンドルの並べ替え
lines = [lines[i] for i in [4, 2, 0, 1, 3]]
labels = [labels[i] for i in [4, 2, 0, 1, 3]]
 
# 最初のライン用の凡例を作成
first_legend = plt.legend(lines[:2], labels[:2], loc='upper left')
 
# 凡例を現在の Axes に手動で追加する
ax.add_artist(first_legend)
 
# その他のための別の凡例を作成する。
plt.legend(lines[2:], labels[2:], loc='lower right')
 
plt.show()

この場合、最初にラインをプロットし、そのハンドルとラベルを保存して、任意の順序に並べ替えます。

Matplotlibの代替方法:PyGWalkerでデータを視覚化

Matplotlibを使用してpandasデータフレームを視覚化することに加えて、データ視覚化を簡単に作成するためのオープンソースPythonライブラリであるPyGWalker (opens in a new tab)があります。

PyGWalker for Data visualization (opens in a new tab)

もうPythonコーディングで複雑な処理を完了する必要はありません。データをインポートして、変数をドラッグアンドドロップして、さまざまなデータ視覚化を作成できます。操作に関するクイックデモ動画は次のとおりです:


Jupyter NotebookでPyGWalkerを使用する方法は次のとおりです。

pip install pygwalker
import pygwalker as pyg
gwalker = pyg.walk(df)

または、Kaggle Notebook/Google Colab で試すことができます。

カグルノートブックでPyGWalkerを実行する (opens in a new tab)Google ColabでPyGWalkerを実行する (opens in a new tab)GitHubでPyGWalkerに⭐️をつける (opens in a new tab)
カグルノートブックでPyGWalkerを実行する (opens in a new tab)Google ColabでPyGWalkerを実行する (opens in a new tab)GitHubでPyGWalkerに⭐️をつける (opens in a new tab)

PyGWalkerは、オープンソースコミュニティのサポートを受けて構築されています。PyGWalker GitHub (opens in a new tab)をチェックして、私たちにスターを付けて忘れないでください!

結論

Matplotlibレジェンドのさまざまなカスタマイズオプションを理解することは、プロフェッショナルグレードのプロットを作成するために不可欠なツールです。したがって、これらのテクニックを練習し、Matplotlibドキュメントを探索してこの重要なデータ可視化ツールに熟達することをお勧めします。

よくある質問

以下では、Matplotlibにおけるレジェンド配置に関するよくある質問について説明します。

Q1:プロット自体のサイズを変更せずに、Matplotlibのレジェンドをプロットエリアの外側に配置できますか?

はい、プロットのサイズを変更せずにレジェンドをプロットの外側に配置することができます。ただし、plt.savefig()のbbox_inches ='tight'オプションが軸の境界外の要素を考慮しない可能性があるため、保存された図ではレジェンドが見えない場合があります。

Q2:Matplotlibには、レジェンドの最適な位置を自動的に決定する方法がありますか?

はい、Matplotlibには、 legend()関数で loc ='best'を渡すことで、自動的にレジェンドの最適な場所を決定する方法があります。この機能は、プロットと重なり合いを最小限に抑える場所にレジェンドを配置します。

Q3:プロットと重なる場合、レジェンドラベルをより読みやすくする方法はありますか?

legend()framealphaパラメータを設定することにより、半透明のレジェンド背景を使用することで、レジェンドラベルの読みやすさを向上させることができます。たとえば、 ax.legend(framealpha = 0.5)では、レジェンドの背景を半透明に設定します。