さて、plotlyを使った線グラフや散布図、棒グラフなどの基本的なグラフの作成方法がわかったところで、今回は2つの水準の違うデータをプロットする“2軸プロット”の方法について解説したいと思います。
以下のようなグラフを作成します。

線グラフの2軸プロット
以下のようなデータセットがあるとします。
“スノーピーク”列がスノーピークの株価、“スノーピーク_リターン”がスノーピークの日次のリターンになっています。
Date スノーピーク スノーピーク_リターン 2019-06-04 1327.55 -0.025937 2019-06-05 1369.77 0.031803 2019-06-06 1382.53 0.009315 2019-06-07 1396.28 0.009946 2019-06-10 1413.96 0.012662 ... ... ... 2021-05-25 3725.00 0.008119 2021-05-26 3555.00 -0.045638 2021-05-27 3575.00 0.005626 2021-05-28 3555.00 -0.005594 2021-05-31 3520.00 -0.009845
この2つの系列を一つのグラフにプロットしたいと思います。
まず、いつも通り、plotly.graph_objectsをインポートしましょう。
import plotly.graph_objects as go
普通に2つの系列をプロットすると以下のようになってしまいます。
fig = go.Figure()
fig.add_trace(go.Scatter(x=df['Date'],
y=df['スノーピーク'],
mode='lines',
name='株価')
)
fig.add_trace(go.Scatter(x=df['Date'],
y=df['スノーピーク_リターン'],
mode='lines',
name='日次リターン')
)

そこで、左の軸が株価、右の軸がリターンを表すように修正したいと思います。
以下のように修正します。
fig = go.Figure()
fig.add_trace(go.Scatter(x=df['Date'],
y=df['スノーピーク'],
mode='lines',
name='株価',
yaxis='y1')
)
fig.add_trace(go.Scatter(x=df['Date'],
y=df['スノーピーク_リターン'],
mode='lines',
name='日次リターン',
yaxis='y2')
)
fig.update_layout(yaxis1=dict(side='left'),
yaxis2=dict(side='right',
showgrid=False,
overlaying='y'))
まず、6行目と12行目で、各データがどちらの軸か?をyaxis='y1'、yaxis='y2'として指定しています。
次に、update_layoutでレイアウトを指定しています。
15行目ではyaxis1は左軸ですよ、とsideという属性で指定しています。
16行目はyaxis2は右側の軸ですよ、と指定し、17行目showgridで右軸のグリッド線を消しています。
18行目のoverlayingを指定しないと1つ目の系列が表示されません。
以上により、表示されるグラフは以下のようになります。

凡例の場所を変えたり、軸ラベルを付けたりといったところは、好みでやっていただければと思います。
棒グラフの2軸プロット
棒グラフも考え方はほぼ同じです。
データとしてはあまり適当ではありませんが、例ということでいったん以下のデータを使います。
本当はもう少し水準の違うデータを使いたいところです。
month スノーピーク ANA 1 1061.782632 3456.911053 2 912.860556 3215.549444 3 661.422381 2743.253810 4 719.312381 2390.619048 5 898.073333 2399.500000 6 1047.870909 2634.022727 7 1168.285714 2392.261905 8 1332.228000 2424.525000 9 1742.916500 2703.625000 10 1906.516667 2394.500000 11 1740.659474 2492.157895 12 1760.100000 2318.886364
これらのデータについて2軸の棒グラフを作成するコードは以下のようになります。
fig = go.Figure()
fig.add_trace(go.Bar(x=[f'{month}月' for month in df_mean['month']],
y=df_mean['スノーピーク'],
yaxis='y1',
offsetgroup=1,
name='スノーピーク'))
fig.add_trace(go.Bar(x=[f'{month}月' for month in df_mean['month']],
y=df_mean['ANA'],
yaxis='y2',
offsetgroup=2,
name='ANA'))
fig.update_layout(yaxis1=dict(side='left'),
yaxis2=dict(side='right',
overlaying='y',
showgrid=False))
fig.update_layout(barmode='group')
線グラフと違うところは、5行目と10行目でoffsetgroup=1, offsetgroup='2としているところと、16行目でbarmode='group'としているところです。
まず16行目はbarmode='group'とすることで積み上げ棒ではなく、グループごとに個別のエリアに棒を立てます。
そして、offsetgroupを1と2という別のグループを指定することで、これらの系列が別の棒として認識されます。

棒グラフと線グラフの2軸プロット
最後に棒グラフと線グラフの両方を使った2軸プロットを作成してみましょう。
こちらも線グラフの場合と同じです。
コードは以下のようになります。
fig = go.Figure()
fig.add_trace(go.Bar(x=[f'{date.month}月{date.day}日' for date in df_sub['Date']],
y=df_sub['スノーピーク'],
name='株価',
width=0.5,
textposition='outside',
texttemplate='%{y:0.0f}円',
hovertemplate='%{x}<br>株価%{y:0.0f}円',
yaxis='y1')
)
fig.add_trace(go.Scatter(x=[f'{date.month}月{date.day}日' for date in df_sub['Date']],
y=df_sub['スノーピーク_リターン']*100,
mode='lines+markers+text',
marker=dict(color='#90ee90',
size=50),
textposition='middle center',
texttemplate='%{y:0.1f}%',
hovertemplate='%{x}<br>リターン:%{y:0.1f}%',
name='日次リターン',
textfont=dict(color='#FFFFFF'),
yaxis='y2')
)
fig.update_layout(yaxis1=dict(side='left',
showgrid=False,
title='株価'),
yaxis2=dict(side='right',
showgrid=False,
overlaying='y',
title='リターン(%)'),
plot_bgcolor='white',
title='スノーピークの株価と日次リターン')
線グラフの2軸プロットがわかっていれば、こちらも簡単ですね。
これにより以下のようなグラフができます。

まとめ
今回は、2軸のグラフの作成方法を見てきました。
慣れるまではなかなか覚えにくいかもしれませんが、使えると便利ですので、是非マスターしていただければと思います。
ただ、この方法は便利ではあるのですが、左軸が何で右軸が何かということを確認しないといけないので、若干わかりにくくなります。
例えば、こちらの本などでは2軸のプロットは推奨されていませんのでご注意いただければと思います。
では次回は複数のプロットを同時に行う方法です。
