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

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

Python+matplotlib で 2つの軸を左右・両方左に描画する

物理では、例えば、β と Energy [MeV/u] のように、同じ量だが異なる表記をすることがある。 これを1つのグラフに同時に表示したいとき、以下のようにする。

import numpy as np
import matplotlib.pyplot as plt

Zs = np.arange(1, 100, 1)
data1 = 0.5+Zs*0.002

mnucleon=931.49432  # MeV

def Energy2Beta(E):
    KE=E
    M=mnucleon
    P=((M+KE)**2-M**2)**0.5
    gamma2 = (1+(P/mnucleon)**2)
    beta = (1-(1/gamma2))**0.5
    return beta

plt.rcParams['figure.figsize'] = [6, 5]
plt.rcParams['figure.dpi'] = 72
plt.rcParams["font.size"] = 14

fig, ax1 = plt.subplots()

color = 'tab:red'
ax1.set_xlabel('Atomic number Z')
ax1.set_ylabel('Beta', color=color)
ax1.plot(Zs, data1, color='black')
ax1.tick_params(axis='y', labelcolor=color)
ax1.set_yticks(np.arange(0.5,0.72,0.025))
ax1.set_ylim(0.5,0.7)

ax2 = ax1.twinx()  # 同じX軸を共有する2番めの軸のインスタンスを作成

color = 'tab:blue'
ax2.set_ylabel('Energy [MeV/u]', color=color)  # xlabelはax1で作成済み
# ax2.plot(Zs, data1, color='tab:orange') # デバッグ用 コメントを外すと、ax1と同じデータを描画される
ax2.tick_params(axis='y', labelcolor=color)
ene_ticks = np.arange(150, 400, 25)
beta_ticks = Energy2Beta(ene_ticks)
ax2.set_yticks(beta_ticks,[str(ene) for ene in ene_ticks]) #文字列として描画するのがポイント

# ax2.spines['right'].set_visible(False) #右側の軸は表示させない
# ax2.spines['left'].set_position(('axes', -0.3)) # 左側の軸を軸の相対位置 -0.2の位置に表示
# ax2.yaxis.set_label_position('left') # labelの位置は左側
# ax2.yaxis.set_ticks_position('left') # ticksの位置は左側

ax2.set_ylim(0.5,0.7)

fig.tight_layout()  # 右側のY軸がはみ出した時に全部を表示させるオプション
plt.show()

2つの軸を左右に表示させる場合

途中のコメントアウトした4行をアンコメント (行頭の#を外す)と、2つの軸を左に表示させることができる。

ax2.spines['right'].set_visible(False) #右側の軸は表示させない
ax2.spines['left'].set_position(('axes', -0.3)) # 左側の軸を軸の相対位置 -0.2の位置に表示
ax2.yaxis.set_label_position('left') # labelの位置は左側
ax2.yaxis.set_ticks_position('left') # ticksの位置は左側