物理の駅 Physics station by 現役研究者

テクノロジーは共有されてこそ栄える

Python+matplotlib legend(凡例)の操作: 記号作成、複数の記号を一つのラベルで表示など

matplotlib公式のlegendのチュートリアルの一部をこの記事で紹介する。

matplotlib.org

matplotlibにおける凡例はplt.legend() とする。 label で指定したグラフの凡例が、グラフの隙間に自動的に描画される。

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

np.random.seed(0)
x = np.random.normal(0,1,10000) #平均0、標準偏差1、N=10000
y = np.random.normal(3,2,10000) #平均3、標準偏差2、N=10000

plt.hist(x, range=[-10,10],bins=100,alpha=0.5,label="data1")
plt.hist(y, range=[-10,10],bins=100,alpha=0.5,label="data2")

xx = np.linspace(-10,10,1000)
yy = scipy.stats.norm.pdf(xx, loc=0, scale=1)*10000/100*20
plt.plot(xx, yy, label="model")

plt.legend()
plt.show()

二つの記号、ここでは青とオレンジのヒストグラムを一つのラベル data で表示したい場合は tupleと、handler_map引数を使う。

import numpy as np
import scipy
import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerTuple

np.random.seed(0)
x = np.random.normal(0,1,10000) #平均0、標準偏差1、N=10000
y = np.random.normal(3,2,10000) #平均3、標準偏差2、N=10000

plt.hist(x, range=[-10,10],bins=100,alpha=0.5,label="h1")
plt.hist(y, range=[-10,10],bins=100,alpha=0.5,label="h2")

xx = np.linspace(-10,10,1000)
yy = scipy.stats.norm.pdf(xx, loc=0, scale=1)*10000/100*20
plt.plot(xx, yy, label="p1")

handles, labels = plt.gca().get_legend_handles_labels()
plt.legend([(handles[0], handles[1]), handles[2]], ['data', 'models'], handler_map={tuple: HandlerTuple(ndivide=None)})
plt.show()

plt.subplots()fig, axを作成した場合

import numpy as np
import scipy
import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerTuple

np.random.seed(0)
x = np.random.normal(0,1,10000) #平均0、標準偏差1、N=10000
y = np.random.normal(3,2,10000) #平均3、標準偏差2、N=10000

fig, ax = plt.subplots()
ax.hist(x, range=[-10,10],bins=100,alpha=0.5,label="h1")
ax.hist(y, range=[-10,10],bins=100,alpha=0.5,label="h2")

xx = np.linspace(-10,10,1000)
yy = scipy.stats.norm.pdf(xx, loc=0, scale=1)*10000/100*20
ax.plot(xx, yy, label="p1")

handles, labels = ax.get_legend_handles_labels()
plt.legend([(handles[0], handles[1]), handles[2]], ['data', 'model'], handler_map={tuple: HandlerTuple(ndivide=None)})

plt.show()

凡例はラベルごとに作成されるので、ラベルを設定しなければその凡例は省略することができる。グラフの描画時にラベルを設定せず、後で記号とラベルの組を作成する場合は以下のようにする。

import numpy as np
import scipy
import matplotlib.pyplot as plt
from matplotlib.patches import Patch
from matplotlib.lines import Line2D

np.random.seed(0)
x = np.random.normal(0,1,10000) #平均0、標準偏差1、N=10000
plt.hist(x, range=[-10,10],bins=100)
xx = np.linspace(-10,10,100)
yy = scipy.stats.norm.pdf(xx, loc=0, scale=1)*10000/100*20
plt.plot(xx, yy, marker="*", markersize=12, alpha=0.5)

handle1 = Patch(facecolor='tab:blue', label='data')
handle2 = Line2D([], [], color='tab:orange', marker='*', markersize=12, alpha=0.5, label='model')
plt.legend([handle1,handle2])
plt.show()

これらを組み合わせることも可能

import matplotlib.pyplot as plt
from matplotlib.patches import Patch
from matplotlib.lines import Line2D
from matplotlib.legend_handler import HandlerTuple

handle1 = Patch(facecolor='tab:blue', alpha=0.5)
handle2 = Patch(facecolor='tab:orange', alpha=0.5)
handle3 = Line2D([], [], color='tab:green')
plt.legend([(handle1,handle2),handle3], ['data', 'model'], handler_map={tuple: HandlerTuple(ndivide=None)})
plt.show()