ここまで順番に読んでいただいている方は、すっかりplotlyを使うようになったのではないでしょうか?
さて今回は、Python Plotlyを使って箱ひげ図(Box Plot)を作成したいと思います。
公式HPの解説はこちらです。
Plotly Expressを使った箱ひげ図(box plot)の作成
基本的なプロット方法
Plotly Expressを使うと、Pandasのデータフレームを使って簡単に作成することが可能です。
以下のような月ごとの株価リターンのデータがあるとします。
month スノーピーク_リターン アルペン_リターン 楽天_リターン ANA_リターン 1 -0.029491 -0.014067 -0.016043 -0.02828 1 0.020892 0.011414 0.015217 0.014128 1 -0.023256 -0.018062 -0.017131 -0.010588 1 0.040955 0.022997 0.006536 0.015487 1 0.004569 -0.011802 -0.004329 -0.004992 ... ... ... ... ... 12 0.011617 -0.003908 0.011 0.01299 12 0.004376 -0.001746 -0.013848 -0.001603 12 0.000543 -0.009168 -0.026078 -0.01445 12 0.007395 0.014673 0.037075 0.047242 12 0.012507 0.035933 -0.01291 0.012
まず、plotly.expressをインポートします。
import plotly.express as px
以下のようにpx.boxを呼び出すだけで箱ひげ図を描くことができます。
px.box(df, y='スノーピーク_リターン')
描画するためのデータフレームdfを第一引数として渡し、yで描画したい列を指定しています。
plotlyなのでインタラクティブなグラフになるため、カーソルを当てると、中央値や四分位点などの数値も見ることができます。
グループごとにプロットする
ここで見たのは、1年間のリターンの箱ひげ図ですが、例えば月ごとに見たいという場合は、xでグループに分割する列を指定します。
この場合だとxはmonthという月を表す列になります。
px.box(df, y='スノーピーク_リターン', x='month')
元データの分布もあわせてプロットする
box plotで集約した結果も重要ですが、元のデータの分布を直接見たい場合もあります。
その場合は、1次元ですが、散布図を付けることも可能です。
その場合は、points='all'を付け加えるだけです。
px.box(df, y='スノーピーク_リターン', x='month', points='all')
複数データをグルーピングしてプロットする
他にもcolorに色分けする列を指定することにより、その列の値でグルーピングしてくれます。
例えば以下のようなスノーピークと楽天のリターンのデータフレームがあるとします。
month return name 1 -0.029491 スノーピーク 1 0.020892 スノーピーク -0.023256 スノーピーク 1 0.040955 スノーピーク 1 0.004569 スノーピーク ... ... ... 12 0.011000 楽天 12 -0.013848 楽天 12 -0.026078 楽天 12 0.037075 楽天 12 -0.012910 楽天
px.boxでcolor="name"を指定します。
px.box(df_vertical, y='return', x='month', color='name')
このままでは見にくいので、皆さまは用途に応じてキレイに整えていただければと思います。
その他、タイトルや色の設定もできますが、ここでは省略します。
plotly graph_objectsを使ったbox plotの作成
基本的なプロット
では、plotly.expressではなく、よりきめ細やかな設定のできるplotly.graph_objectsを使った棒グラフの作成方法を見ていきましょう。
plotly.expressは非常にシンプルですが、plotly.graph_objectsもそれほど大変なわけではないので、個人的にはこちらをオススメします。
まず、plotly.graph_objectsをインポートします。
import plotly.graph_objects as go
そして、go.Box()を呼び出します。
引数は最低限yにデータを渡してやるだけです。
あとはnameなどで凡例を設定します。
fig = go.Figure() fig.add_trace(go.Box(y=df['スノーピーク_リターン'], name='スノーピーク')) fig.add_trace(go.Box(y=df['楽天_リターン'], name='楽天'))
これだけでシンプルな箱ひげ図が作成できます。
グループごとにプロットする
月ごとのリターンを見たい場合は、xに分けたいグループを指定します。
この場合だと、データフレームのmonthという列に月の情報が入っているので、x=df["month"]とすることで、month列で分けることができます。
fig = go.Figure() fig.add_trace(go.Box(y=df['スノーピーク_リターン'], x=df['month'], name='スノーピーク' ))
複数データをグルーピングしてプロットする
続いて、スノーピークと楽天の月次リターンを比較したい場合です。
その場合もxに月を表す列を指定して、楽天のデータも渡すだけです。
fig = go.Figure() fig.add_trace(go.Box(y=df['スノーピーク_リターン'], x=df['month'], name='スノーピーク' )) fig.add_trace(go.Box(y=df['楽天_リターン'], x=df['month'], name='楽天'))
ただこのままだと、以下のようにスノーピークと楽天のデータが被ってしまいます。
これを回避するために、レイアウトを設定する必要があります。
update_layoutでboxmode="group"としてやります。
元データもあわせてプロットする
plotly expressのときと同様に、散布図を横に描きたい場合は、boxpoints="all"を指定します。
ここではjitter=0.3として散布図の幅(広がり方)を指定しています。
fig = go.Figure() fig.add_trace(go.Box(y=df.query('month==7')['スノーピーク_リターン'], name='スノーピーク' )) fig.add_trace(go.Box(y=df.query('month==7')['楽天_リターン'], name='楽天' )) fig.add_trace(go.Box(y=df.query('month==7')['ANA_リターン'], name='ANA' )) fig.update_traces(boxpoints='all', jitter=0.3)
集約した結果だけでなく、実際のデータもあると少し安心しますね。
水平にプロットする
棒グラフのように水平方向にするには、traceでorientaion="h"とします。
また、xとyは入れ替えないといけません。
ここでは、xだけ指定したいと思います。
また、update_tracesでまとめてorientaion="h"と設定します。
fig = go.Figure() fig.add_trace(go.Box(x=df['スノーピーク_リターン'], name='スノーピーク' )) fig.add_trace(go.Box(x=df['楽天_リターン'], name='楽天')) fig.update_traces(orientation='h') fig.update_layout( boxmode='group', )
(おまけ) レイアウトを整える
最後に少しだけレイアウトを整えましょう。
以下のコードで不要なものは除いて見やすくします。
レイアウトの整え方についてはこちらの記事ご参照ださい。
fig = go.Figure() fig.add_trace(go.Box(y=df.query('month==7')['スノーピーク_リターン'], name='<b>スノーピーク', )) fig.add_trace(go.Box(y=df.query('month==7')['ANA_リターン'], name='<b>ANA', marker_color='lightblue' )) fig.add_trace(go.Box(y=df.query('month==7')['楽天_リターン'], name='<b>楽天', marker_color='grey' )) fig.update_traces(boxpoints='all', jitter=0.3, ) fig.update_yaxes(title=dict(text='リターン(%)'), tickformat='%', showline=True, linewidth=1, linecolor='lightgrey', color='grey') fig.update_xaxes(showline=True, linewidth=1, linecolor='lightgrey', color='grey', tickfont={'size': 17}) fig.update_layout(plot_bgcolor='white', title=dict(text='<b>2020年7月の各銘柄のリターン', font_color='grey', font_size=22, y=0.9 ), showlegend=False )
もう少し誰かに説明したくなるような結果であればよかったのですが、多少特徴はあるものの、これと言って主張したくなるようなものではありませんでした。
皆さまがお客さんや上司の方へのプレゼンをする際は、うまく伝えたいところを強調していただければと思います。
ちなみに、伝わるデータ可視化技術については以下の本が超オススメです。
Storytelling with Data: A Data Visualization Guide for Business Professionals (English Edition)まとめ
今回はplotlyを使った箱ひげ図(box plot)使い方を紹介しました。
もう少しグラフをわかりやすいものにするには、レイアウト設定を行う必要がありますが、それについては以下の記事で細かく解説していますので、参考にしていただければと思います。
次は、アノテーションの仕方を解説したいと思います!