HOWTO · Matplotlib

Matplotlib でセカンダリ Y 軸に Y 軸ラベルを追加する方法

Axes オブジェクトと対話し、pandas.DataFrame.plot メソッドを直接使用して、Matplotlib の 2 番目の y 軸に y 軸ラベルを追加できます。

このページの内容

Matplotlibで第2のy軸にラベルを付けるには、Axes.twinx()が返す第2のaxesに対してset_ylabel()を呼び出します。返されたaxesオブジェクトはプロットのx軸を共有し、反対側に独立したy軸を持ちます。量の違いが分かる説明的なラベルを付け、必要に応じて単位も含めましょう。

twinx()で第2のy軸にラベルを付ける

ax.twinx()で2つ目のaxesを作成し、2つ目のデータ系列をそこにプロットして、そのaxesに直接ラベルを設定します。この例では両方の色を定義し、ラベルを配置する余白を確保するためにtight_layout()を使います。

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 5, 100)
fig, ax = plt.subplots()
ax.plot(x, np.sin(x), color="tab:blue")
ax.set_xlabel("Time (s)")
ax.set_ylabel("sin(x)", color="tab:blue")
ax.tick_params(axis="y", labelcolor="tab:blue")

ax2 = ax.twinx()
ax2.plot(x, np.cos(x), color="tab:orange")
ax2.set_ylabel("cos(x)", color="tab:orange")
ax2.tick_params(axis="y", labelcolor="tab:orange")

fig.tight_layout()
plt.show()

左側の青い y 軸に sin(x)、右側のオレンジ色の第 2 y 軸に cos(x) のラベルが付いたグラフ。両曲線とも Time (s) に対して描かれています。

ax2が第2のaxesなので、ax2.set_ylabel(...)を呼び出すと右側のy軸にラベルが付きます。代わりにaxへset_ylabel()を適用すると、左側にある主軸のラベルが変わります。ラベルや目盛りの色を各線の色に合わせるのは任意ですが、2つのスケールを見分けやすくするのに役立ちます。

1つ目の例を表示すると、横軸にはTime (s)と表示されます。青い正弦曲線は左のy軸、オレンジ色の余弦曲線は右のy軸を使います。どちらの曲線も同じ時間の値にわたって描かれますが、それぞれの縦方向のスケールは図の別々の側で読み取ります。記事のメイン画像にはHeightとWeightの軸が描かれていますが、これは別の図であり、例の正弦曲線や余弦曲線を示したものではありません。コード内の軸ラベルは変更せず英語のまま表示されます。

y軸ラベルを分かりやすく整える

Temperature (°C)やPressure (kPa)のように、測定する量と単位が分かるテキストを選びます。スタイルの指定は必須ではありませんが、読みやすさが向上する場合はcolor、fontsize、fontweightなどの引数をset_ylabel()に渡せます。ラベルをそれぞれ異なる内容にし、どのデータがどのスケールに対応するかを色だけで説明しないようにしましょう。

次の例では、左の目盛りが摂氏温度、右の目盛りがキロパスカル単位の圧力を示すグラフに、これらのスタイル指定を適用します。

import matplotlib.pyplot as plt
import numpy as np

hours = np.arange(0, 24, 2)
temperature = 18 + 4 * np.sin((hours - 9) * np.pi / 12)
pressure = 101.3 + 0.8 * np.cos((hours - 6) * np.pi / 12)

fig, ax = plt.subplots()
ax.plot(hours, temperature, color="tab:red", marker="o")
ax.set_xlabel("Hour of day")
ax.set_ylabel(
    "Temperature (°C)", color="tab:red", fontsize=12, fontweight="bold"
)
ax.tick_params(axis="y", labelcolor="tab:red")

ax2 = ax.twinx()
ax2.plot(hours, pressure, color="tab:green", marker="s")
ax2.set_ylabel(
    "Pressure (kPa)", color="tab:green", fontsize=12, fontweight="bold"
)
ax2.tick_params(axis="y", labelcolor="tab:green")

fig.tight_layout()
plt.show()

左側の y 軸に太字の赤い Temperature (°C) ラベル、右側の第 2 y 軸に太字の緑の Pressure (kPa) ラベルが付いたグラフ。

各ラベルは、グラフのその側で読み取る値を短く説明するものと考えてください(上の例のように)。テキストと単位で数値の意味を伝え、線とラベルの色を合わせる方法は補助的な手がかりとして使います。ラベルが詰まって見える場合は、tight_layout()で図の余白を調整できますが、長いラベルには図を大きくするか、文言を短くする必要があることもあります。

DataFrame.plotで第2のy軸にラベルを付ける

pandasのデータを使う場合は、secondary_y=Trueを指定して2つ目の系列をプロットするときに、最初のプロットのaxesをaxに渡します。DataFrame.plotは呼び出しごとにaxesオブジェクトを返します。最初の呼び出しは主軸のaxesを返し、2回目は第2のaxesを返すので、それぞれ対応するオブジェクトにラベルを設定します。

import matplotlib.pyplot as plt
import pandas as pd

frame = pd.DataFrame({
    "age": [10, 20, 30, 40],
    "height": [120, 140, 160, 170],
    "weight": [30, 45, 60, 70],
})

ax = frame.plot(x="age", y="height", color="tab:blue")
ax2 = frame.plot(
    x="age", y="weight", secondary_y=True, ax=ax, color="tab:orange"
)
ax.set_ylabel("Height (cm)")
ax2.set_ylabel("Weight (kg)")
plt.tight_layout()
plt.show()

pandas DataFrame.plot のグラフ。左側の y 軸に Height (cm)、右側の第 2 y 軸に Weight (kg) が表示され、両系列とも age に対して描かれています。

ここではsecondary_yによってweightに右側のスケールを割り当て、ax=axによって同じ図にその系列を重ねています。列名や単位を変える場合は、プロットするデータに合うようにyの引数とラベルの両方を更新してください。

この例の値でグラフを表示すると、横軸は年齢、左側はHeight (cm)、右側はWeight (kg)になります。青いheightの線は4つの年齢にわたって上昇し、オレンジ色のweightの線も上昇します。2本の線は、それぞれ対応するy軸ラベルとスケールに基づいて読み取ります。実際にプロットする列に合わせてラベルを付け、選択する列や単位を変えたらラベルも変更してください。既存のaxを渡すと両方の系列が同じ図に描かれ、secondary_y=Trueによって2つ目の系列に右側のスケールが割り当てられます。例のコード内にあるラベル文字列は変更せず英語のまま表示されます。