plotly入門 データ可視化

Python Plotly入門 - 箱ひげ図(Box Plot)

2021年7月3日

ここまで順番に読んでいただいている方は、すっかり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)使い方を紹介しました。

もう少しグラフをわかりやすいものにするには、レイアウト設定を行う必要がありますが、それについては以下の記事で細かく解説していますので、参考にしていただければと思います。

次は、アノテーションの仕方を解説したいと思います!

-plotly入門, データ可視化
-,