Matplotlibで棒グラフの凡例をカスタマイズする方法【Python】

Matplotlibで棒グラフの凡例をカスタマイズする方法【Python】 プログラミング

「Matplotlibで作成する棒グラフをもっと良いモノにしたい」
このように考える方向けの内容となります。

「Matplotlibでとにかく棒グラフを作成したい」と思う方は、次の記事をご覧ください。
内容としては、初級レベルになります。
本記事内では、この記事を初級レベル記事と言います。

上の記事の続編になるのが、次の記事です。
内容としては、中級レベルになります。
本記事内では、この記事を中級レベル記事と言います。

この記事もその流れを受けての続々編です。
中級以上で上級未満という感じですね。
この記事を読めば、以下の棒グラフを作成できるようになります。

本記事の内容

  • 過去記事の内容で作成できる棒グラフを確認する
  • ゴール(wikipedia「棒グラフ」の棒グラフ画像)と比較する
  • Matplotlibで棒グラフにおいて凡例の枠線を消す
  • Matplotlibで棒グラフにおいて凡例の表示位置を微調整する
  • Matplotlibで棒グラフにおいて凡例のアイコンサイズを変更する

過去記事の内容で作成できる棒グラフを確認する

まず、過去の初級レベル記事と中級レベル記事で作成できる棒グラフを確認します。

初級レベル記事で作成した棒グラフ

中級レベル記事の内容に沿って作成した棒グラフ
以下、中級レベルグラフと呼びます。

現状、上の棒グラフまで作成できるようになっています。
初級レベル・中級レベルの記事通りにすれば、このレベルの棒グラフが作成できるということです。

とりあえず、この時点でのコードを載せておきます

import math
import numpy as np
import matplotlib.pyplot as plt

labels = ['EUL', 'PES', 'EFA', 'EDD', 'ELDR', 'EPP', 'UEN', 'その他']
values_1999 = [49, 210, 56, 19, 60, 272, 36, 29]
values_2004 = [39, 200, 42, 15, 67, 276, 27, 66]
values = values_1999 + values_2004

fig = plt.figure(dpi=100, figsize=(4.8,2.4))
fig.suptitle('欧州議会選挙', fontsize=9, y=0.93)
ax = fig.add_subplot(111)
ax.yaxis.set_label_coords(-0.07,1.08)

g_width = 0.35
lefts_1999 = np.arange(len(values_1999))
lefts_2004 = lefts_1999 + g_width
p_1999 = plt.bar(lefts_1999, values_1999, width=g_width, color="#666666")
p_2004 = plt.bar(lefts_2004, values_2004, width=g_width, color="#b2b2b2")

scale_num = 50
y_max = (math.ceil(max(values) / scale_num) + 1 ) * scale_num
yscale = np.arange(0, y_max, scale_num)

plt.xticks(lefts_1999 + g_width/2, labels, fontsize=8)
plt.yticks(yscale, fontsize=8)
#plt.title("欧州議会選挙")
plt.xlabel("政党", fontsize=8)
plt.ylabel("議席数", fontsize=8, rotation=0)
plt.gca().spines['right'].set_visible(False)
plt.gca().spines['top'].set_visible(False)
plt.legend((p_1999[0], p_2004[0]), ("1999", "2004"), loc='upper center', ncol=2, fontsize=8)

plt.subplots_adjust(left=0.11, right=0.9, bottom=0.2, top=0.8)
plt.savefig("result.png", facecolor="white")

もし、内容を理解できていない方は、過去記事をご覧ください。
すぐに実行できるプログラムのコードも載せています。

ゴール(wikipedia「棒グラフ」の棒グラフ画像)と比較する

Matplotlibの棒グラフを作成するシリーズ(過去記事)では、目標となるゴールを定めています。
そのゴールは、wikipedia「棒グラフ」ページにある棒グラフ画像です。

本記事でも、ゴールは同じです。
それが以下の棒グラフです。

上記の中級レベルグラフと比較すると、残すは凡例の部分だけですね。
日本語の違いは、無視してください。

なお、Matplotlibで日本語が文字化けする場合は、次の記事をご覧ください。
文字化けの解消方法を詳細に説明しています。

さて、差分の凡例に話を戻しましょう。
凡例をゴールに近づけるためには、以下の対応が必要です。

  • Matplotlibで棒グラフにおいて凡例の枠線を消す
  • Matplotlibで棒グラフにおいて凡例の表示位置を微調整する
  • Matplotlibで棒グラフにおいて凡例のアイコンサイズを変更する

Matplotlibで棒グラフにおいて凡例の枠線を消す

凡例は、以下のコード表現しています。

plt.legend((p_1999[0], p_2004[0]), ("1999", "2004"), loc='upper center', ncol=2, fontsize=8)

凡例の枠線を消すためには、以下の二つの引数を理解する必要があります。

  • shadow
  • framealpha

shadow

値:None または bool
凡例の後ろに影を描くかどうか。
デフォルトはNone(Falseと同じ)。

True False

framealpha

値:None または float
凡例の背景のアルファ透明度。
デフォルトは None (0.8を指定していることと同じ)。
shadowが有効でframealphaがNoneの場合、デフォルト値は無視されます。

現状のコード。

plt.legend((p_1999[0], p_2004[0]), ("1999", "2004"), loc='upper center', ncol=2, fontsize=8)

現状では、shadow=False、framealpha=0.8ということです。

凡例の枠線を消す

透明度を最大(0.0)にすれば、枠線は消えます。
ただし、shadow=Falseである必要があります。

以下のコードとなります。
shadow=Falseを明示的に記述した方が、わかりやすいです。

plt.legend((p_1999[0], p_2004[0]), ("1999", "2004"), loc='upper center', ncol=2, fontsize=8, shadow=False, framealpha=0.0)

この変更の結果は以下。

凡例の枠線が消えました。
この結果、凡例の位置をもっと上にする必要性が出てきました。

グラフと被ってますからね。
では、次は凡例の位置をさらに上に移動させましょう。

Matplotlibで棒グラフにおいて凡例の表示位置を微調整する

すでに凡例の位置は制御しています。
下記コードの「loc=’upper center’」によってです。

plt.legend((p_1999[0], p_2004[0]), ("1999", "2004"), loc='upper center', ncol=2, fontsize=8, shadow=False, framealpha=0.0)

しかし、さらに上に移動させる必要があります。
そのような場合には、bbox_to_anchorを利用します。

bbox_to_anchorを利用する場合、locと組み合わせることになります。
bbox_to_anchorを引数に追加した場合、locでの指定した意味合いが変わるとも言えます。

どのように変わるのかと言うと、実際の例を見てみましょう。
そちらの方が理解が進みます。

なお、locの値は、以下から選択します。

Location StringLocation Code
‘best’0
‘upper right’1
‘upper left’2
‘lower left’3
‘lower right’4
‘right’5
‘center left’6
‘center right’7
‘lower center’8
‘upper center’9
‘center’10

例えば、bbox_to_anchor=(1, 1) を指定した場合
locが、次の値である場合の「凡例」の位置を表しています。

upper rightupper leftupper center

つまり、凡例を表現するボックス(以下、凡例ボックス)の位置が、bbox_to_anchorの値だということです。
「upper right」であれば、凡例ボックス右上の座標が(1, 1)となります。
「upper left」であれば、凡例ボックス左上の座標が(1, 1)となります。
「upper right」であれば、凡例ボックス真ん中上の座標が(1, 1)となります。

今回は中央の上部に凡例を表示することが、ミッションです。
よって、以下のようなコードとなります。

plt.legend((p_1999[0], p_2004[0]), ("1999", "2004"), loc='upper center', bbox_to_anchor=(0.5, 1.06),
           ncol=2, fontsize=8, shadow=False, framealpha=0.0)

この変更を反映した結果は以下。

若干、凡例ボックスを上に移動させることができました。
あとは、凡例ボックスの中を調整するだけです。

Matplotlibで棒グラフにおいて凡例のアイコンサイズを変更する

凡例のアイコンサイズを変更していきます。
ただし、アイコンサイズ以外にも変更できるものは変更します。

変更対象は以下。

  • アイコンサイズ
  • アイコンと文字の間のスペース
  • カラム間のスペース

それぞれの引数は以下。

アイコンサイズhandlelength
アイコンと文字の間のスペースhandletextpad
カラム間のスペースcolumnspacing

handlelength

値:float or None
凡例のハンドル(アイコン)の長さ。
フォントサイズの単位で測定されます。
デフォルトは None(この場合、2.0が初期値)。

handletextpad

値:float or None
凡例ハンドル(アイコン)とテキストの間のスペース。
フォントサイズの単位で測定されます。
デフォルトは None(この場合、0.8が初期値)。

columnspacing

値:float or None
列間の間隔。
フォントサイズの単位で測定される。
デフォルトは None(この場合、2.0が初期値)。

修正コード

調整後のコードは以下。

plt.legend((p_1999[0], p_2004[0]), ("1999", "2004"), loc='upper center',bbox_to_anchor=(0.5, 1.06),           columnspacing=0.8, handletextpad=0.3,  handlelength=0.7,           ncol=2, fontsize=8, shadow=False, framealpha=0.0)

上記を反映させた最終的なコードは以下。

import math
import numpy as np
import matplotlib.pyplot as plt

labels = ['EUL', 'PES', 'EFA', 'EDD', 'ELDR', 'EPP', 'UEN', 'その他']
values_1999 = [49, 210, 56, 19, 60, 272, 36, 29]
values_2004 = [39, 200, 42, 15, 67, 276, 27, 66]
values = values_1999 + values_2004

fig = plt.figure(dpi=100, figsize=(4.8,2.4))
fig.suptitle('欧州議会選挙', fontsize=9, y=0.93)
ax = fig.add_subplot(111)
ax.yaxis.set_label_coords(-0.07,1.08)

g_width = 0.35
lefts_1999 = np.arange(len(values_1999))
lefts_2004 = lefts_1999 + g_width
p_1999 = plt.bar(lefts_1999, values_1999, width=g_width, color="#666666")
p_2004 = plt.bar(lefts_2004, values_2004, width=g_width, color="#b2b2b2")

scale_num = 50
y_max = (math.ceil(max(values) / scale_num) + 1 ) * scale_num
yscale = np.arange(0, y_max, scale_num)

plt.xticks(lefts_1999 + g_width/2, labels, fontsize=8)
plt.yticks(yscale, fontsize=8)
#plt.title("欧州議会選挙")
plt.xlabel("政党", fontsize=8)
plt.ylabel("議席数", fontsize=8, rotation=0)
plt.gca().spines['right'].set_visible(False)
plt.gca().spines['top'].set_visible(False)
plt.legend((p_1999[0], p_2004[0]), ("1999", "2004"), loc='upper center',bbox_to_anchor=(0.5, 1.06),
           columnspacing=0.8, handletextpad=0.3,  handlelength=0.7,
           ncol=2, fontsize=8, shadow=False, framealpha=0.0)

plt.subplots_adjust(left=0.11, right=0.9, bottom=0.2, top=0.8)
plt.savefig("result.png", facecolor="white")

実行結果は以下。

ゴールに到達です。
wikipedia「棒グラフ」の画像とほぼ同じになりました。

以上にて、Matplotlibで棒グラフの凡例をカスタマイズする方法の説明は終了です。
これである程度の棒グラフは、Matplotlibを利用して出力できると思います。

タイトルとURLをコピーしました