Warning: Undefined variable $position in /home/pystyles/pystyle.info/public_html/wp/wp-content/themes/lionblog/functions.php on line 4897

matplotlib – legend でグラフに凡例を表示する方法

matplotlib – legend でグラフに凡例を表示する方法

概要

matplotlib でグラフに凡例 (legend) を表示する方法について解説します。

Advertisement

legend

凡例を表示する

何も引数を指定しない場合、折れ線などの描画物を作成した際に label 引数で指定したラベルが凡例に表示されます。

In [1]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 1000)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots(facecolor="w")
ax.plot(x, y1, label="sin")
ax.plot(x, y2, label="cos")
ax.legend()
plt.show()

凡例のラベルを指定する

折れ線などの描画物を作成した際に label 引数で指定したラベルとは別のラベルを表示したい場合は、ラベルのリストを指定します。

In [2]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 1000)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots(facecolor="w")
ax.plot(x, y1, label="sin")
ax.plot(x, y2, label="cos")

ax.legend(["A", "B"])

plt.show()

指定した Artist に凡例をつける

折れ線などの描画物を作成した際の返り値である Artist とラベルをそれぞれリストで渡すことでも凡例を作成できます。

In [3]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 1000)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots(facecolor="w")
(line1,) = ax.plot(x, y1, label="sin")
(line2,) = ax.plot(x, y2, label="cos")

ax.legend([line1, line2], ["A", "B"])

plt.show()

凡例の位置を指定する

bbox_to_anchor=(x, y, width, height)loc で指定した場合

bbox_to_anchor は、Axes 座標系 (左下が (0, 0)、右上が (1, 1)) で、凡例を配置する際の基準となる矩形の位置及び大きさになります。この矩形内の loc で指定した場所に凡例が配置されます。borderaxespad で矩形と凡例の間のパディングをフォントサイズ単位で指定できます。

bbox_to_anchor と loc を利用した凡例の位置指定

locbbox_to_anchor 内の相対位置で指定します。(わかりやすいように bbox_to_anchor を赤で可視化しています)

In [4]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 1000)
y1 = np.sin(x)
y2 = np.cos(x)

locs = [
    "upper left",
    "upper right",
    "lower left",
    "lower right",
    "center left",
    "center right",
    "upper center",
    "lower center",
    "center",
    "best",
    "right",
]

fig = plt.figure(figsize=(8, 15), facecolor="w")
plt.subplots_adjust(hspace=0.5)

for i, loc in enumerate(locs, 1):
    ax = fig.add_subplot(6, 2, i)
    ax.plot(x, y1, label="sin")
    ax.plot(x, y2, label="cos")
    ax.set_title(f"loc='{loc}'")
    ax.legend(loc=loc, bbox_to_anchor=(0.5, 0, 0.5, 1))

    # わかりやすいように bbox_to_anchor を可視化する。
    rect = plt.Rectangle(
        (0.5, 0),
        0.5,
        1,
        edgecolor="r",
        facecolor="none",
        clip_on=False,
        lw=2,
        zorder=10,
    )
    rect.set_transform(ax.transAxes)  # axes 座標系に指定する。
    ax.add_patch(rect)

plt.show()

loc=(x, y) を指定した場合

loc=(x, y) と指定した場合、Axes 座標系 (左下が (0, 0)、右上が (1, 1)) で、凡例の左下がこの位置にくるように配置されます。このとき、bbox_to_anchorborderaxespad は無視されます。

loc を利用した凡例の位置指定

In [5]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 1000)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots(figsize=(5, 3), facecolor="w")
ax.plot(x, y1, label="sin")
ax.plot(x, y2, label="cos")

ax.legend(loc=(0.1, 0.1))
plt.show()

bbox_to_anchor=(x, y)loc で指定した場合

bbox_to_anchor=(x, y) と指定した場合、Axes 座標系 (左下が (0, 0)、右上が (1, 1)) で、この位置に凡例を配置する際の基準となる点を作成します。凡例は loc で指定した位置がこの基準点にくるように配置されます。

In [6]:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.patches import Circle

x = np.linspace(0, 10, 1000)
y1 = np.sin(x)
y2 = np.cos(x)

fig = plt.figure(figsize=(8, 15), facecolor="w")
plt.subplots_adjust(hspace=0.5)

locs = [
    "upper left",
    "upper right",
    "lower left",
    "lower right",
    "center left",
    "center right",
    "upper center",
    "lower center",
    "center",
    "best",
    "right",
]

cols = 2
rows = np.ceil(len(locs) / cols)
for i, loc in enumerate(locs, 1):
    ax = fig.add_subplot(rows, cols, i)
    ax.plot(x, y1, label="sin")
    ax.plot(x, y2, label="cos")
    ax.set_title(f"loc='{loc}'")

    ax.legend(loc=loc, bbox_to_anchor=(0.5, 0.2), borderaxespad=0)

    # わかりやすいように bbox_to_anchor を可視化する。
    circle = Circle((0.5, 0.2), 0.02, facecolor="r", zorder=10, clip_on=False)
    circle.set_transform(ax.transAxes)  # axes 座標系
    ax.add_patch(circle)

plt.show()

凡例の列数を指定する

ncol で凡例の列数を指定できます。(デフォルトは1)

In [7]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 1000)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots(figsize=(5, 3), facecolor="w")
ax.plot(x, y1, label="sin")
ax.plot(x, y2, label="cos")
ax.legend(ncol=2)

plt.show()

点付きの折れ線グラフの場合

凡例の点の数を指定する

点付きの折れ線グラフの場合、numpoints で凡例の点の数を指定できます。 デフォルトは rcParams["legend.numpoints"] の値を使用します。

In [8]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 10)
y1 = np.sin(x)
y2 = np.cos(x)

fig = plt.figure(figsize=(5, 8), facecolor="w")

for i, param in enumerate([1, 2, 3], 1):
    ax = fig.add_subplot(3, 1, i)
    ax.plot(x, y1, "ro-", ms=3, label="sin")
    ax.plot(x, y2, "bo-", ms=3, label="cos")
    ax.set_title(f"numpoints={param}")
    ax.legend(numpoints=param)

plt.show()

凡例の点の大きさを指定する

点付きの折れ線グラフの場合、markerscale で凡例の点の大きさを指定できます。 デフォルトは rcParams["legend.markerscale"] の値を使用します。

In [9]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 10)
y1 = np.sin(x)
y2 = np.cos(x)

fig = plt.figure(figsize=(5, 8), facecolor="w")

for i, param in enumerate([1, 2, 3], 1):
    ax = fig.add_subplot(3, 1, i)
    ax.plot(x, y1, "ro-", ms=3, label="sin")
    ax.plot(x, y2, "bo-", ms=3, label="cos")
    ax.set_title(f"markerscale={param}")
    ax.legend(markerscale=param)

plt.show()
Advertisement

マーカーをラベルの前に持ってくるかどうかを指定する

markerfirst=True の場合、左からマーカー、ラベルの順に配置し (デフォルト)、markerfirst=False の場合、左からラベル、マーカーの順に配置します。

In [10]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 10)
y1 = np.sin(x)
y2 = np.cos(x)

fig = plt.figure(figsize=(5, 8), facecolor="w")

for i, param in enumerate([True, False], 1):
    ax = fig.add_subplot(2, 1, i)
    ax.plot(x, y1, "ro-", ms=3, label="sin")
    ax.plot(x, y2, "bo-", ms=3, label="cos")
    ax.set_title(f"markerfirst={param}")
    ax.legend(markerfirst=param)

plt.show()

凡例の枠を指定する

凡例の枠を付けるかどうかを指定する

frameon で凡例の枠を付けるかどうかを指定できます。 デフォルトは rcParams["legend.frameon"] の値を使用します。

In [11]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 10)
y1 = np.sin(x)
y2 = np.cos(x)

fig = plt.figure(figsize=(5, 8), facecolor="w")

for i, param in enumerate([True, False], 1):
    ax = fig.add_subplot(2, 1, i)
    ax.plot(x, y1, "ro-", ms=3, label="sin")
    ax.plot(x, y2, "bo-", ms=3, label="cos")
    ax.set_title(f"frameon={param}")
    ax.legend(frameon=param)

plt.show()

凡例の枠の角を丸めるかどうかを指定する

fancybox で凡例の枠の角を丸めるかどうかを指定できます。 デフォルトは rcParams["legend.fancybox"] の値を使用します。

In [12]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 10)
y1 = np.sin(x)
y2 = np.cos(x)

fig = plt.figure(figsize=(5, 8), facecolor="w")

for i, param in enumerate([True, False], 1):
    ax = fig.add_subplot(2, 1, i)
    ax.plot(x, y1, "ro-", ms=3, label="sin")
    ax.plot(x, y2, "bo-", ms=3, label="cos")
    ax.set_title(f"fancybox={param}")
    ax.legend(fancybox=param)

plt.show()

凡例の枠に影をつけるかどうかを指定する

shadow で凡例の枠に影をつけるかどうかを指定できます。 デフォルトは rcParams["legend.shadow"] の値を使用します。

In [13]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 10)
y1 = np.sin(x)
y2 = np.cos(x)

fig = plt.figure(figsize=(5, 8), facecolor="w")

for i, param in enumerate([True, False], 1):
    ax = fig.add_subplot(2, 1, i)
    ax.plot(x, y1, "ro-", ms=3, label="sin")
    ax.plot(x, y2, "bo-", ms=3, label="cos")
    ax.set_title(f"shadow={param}")
    ax.legend(shadow=param)

plt.show()

凡例を透過するかどうかを指定する

framealpha で凡例の透過度を指定できます。 デフォルトは rcParams["legend.framealpha"] の値を使用します。

In [14]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 10)
y1 = np.sin(x)
y2 = np.cos(x)

fig = plt.figure(figsize=(5, 8), facecolor="w")

for i, param in enumerate([0.3, 0.5, 1], 1):
    ax = fig.add_subplot(3, 1, i, facecolor="lightgray")
    ax.plot(x, y1, "ro-", ms=3, label="sin")
    ax.plot(x, y2, "bo-", ms=3, label="cos")
    ax.set_title("framealpha={}".format(param))
    ax.legend(framealpha=param)

plt.show()

凡例の色を指定する

facecolor で凡例の色を指定できます。 デフォルトは rcParams["legend.facecolor"] の値を使用します。facecolor="inherit" を指定した場合、rcParams["axes.facecolor"] の値を使用します。

In [15]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 10)
y1 = np.sin(x)
y2 = np.cos(x)

fig = plt.figure(figsize=(5, 8), facecolor="w")

for i, param in enumerate(["pink", "lightgreen", "lightblue"], 1):
    ax = fig.add_subplot(3, 1, i, facecolor="lightgray")
    ax.plot(x, y1, "ro-", ms=3, label="sin")
    ax.plot(x, y2, "bo-", ms=3, label="cos")
    ax.set_title(f"facecolor='{param}'")
    ax.legend(facecolor=param)

plt.show()

凡例の枠の色を指定する

edgecolor で凡例の色を指定できます。デフォルトは rcParams["legend.edgecolor"] の値を使用します。edgecolor="inherit" を指定した場合、rcParams["axes.edgecolor"] の値を使用します。

In [16]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 10)
y1 = np.sin(x)
y2 = np.cos(x)

fig = plt.figure(figsize=(5, 8), facecolor="w")

for i, param in enumerate(["pink", "lightgreen", "lightblue"], 1):
    ax = fig.add_subplot(3, 1, i, facecolor="lightgray")
    ax.plot(x, y1, "ro-", ms=3, label="sin")
    ax.plot(x, y2, "bo-", ms=3, label="cos")
    ax.set_title(f"edgecolor='{param}'")
    ax.legend(edgecolor=param)

plt.show()

凡例の枠を Axes の横幅に広げる

mode="expand" を指定した場合、凡例を Axes の横幅に広げます。bbox_to_anchor を指定している場合、凡例の広がる幅はこの矩形内になります。

In [17]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 10)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots(figsize=(5, 3), facecolor="w")

ax.plot(x, y1, label="sin")
ax.plot(x, y2, label="cos")
ax.legend(mode="expand", loc="lower center", bbox_to_anchor=(0.5, 0, 0.5, 1))

plt.show()

凡例にタイトルをつける

title で凡例にタイトルを指定できます。

In [18]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 10)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots(figsize=(5, 3), facecolor="w")

ax.plot(x, y1, label="sin")
ax.plot(x, y2, label="cos")
ax.legend(title="title", title_fontsize=12)

plt.show()

凡例内のラベル、マーカーの配置を指定する

引数 デフォルト値 単位
borderpad 凡例の枠とラベルのスペース rcParams["legend.borderpad"]
labelspacing ラベル間のスペース rcParams["legend.labelspacing"] フォントサイズ
handlelength ハンドルの長さ rcParams["legend.handlelength"] フォントサイズ
handletextpad ハンドルとラベルのスペース rcParams["legend.handletextpad"]
columnspacing 列が2列以上のとき、列の間のスペース rcParams["legend.columnspacing"]

スペース関係の引数

In [19]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 10)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots(figsize=(5, 3), facecolor="w")

ax.plot(x, y1, label="sin")
ax.plot(x, y2, label="cos")
ax.legend(borderpad=1, labelspacing=1, handlelength=4, handletextpad=1)

plt.show()
In [20]:
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10, 10)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots(figsize=(5, 3), facecolor="w")

ax.plot(x, y1, label="sin")
ax.plot(x, y2, label="cos")
ax.legend(ncol=2, columnspacing=1)

plt.show()