はじめに
グラフの描画といえばmatplotlib + serbornがメジャーですよね。
これらを超えるポテンシャルを秘めたのがインタラクティブなグラフが作成可能なplotly express。
plotly expressを使うとmatplotlib + seabornよりも便利な点に焦点を当てて紹介したいと思います。
plotly express、あまり癖がない印象です。plotlyと比較して行数少なくグラフがプロットでき、matplotlibを使ったことがある方はあまり違和感なく導入できると思います。
個人的に考えるplotly expressが役に立つシーンはこんな感じです。
- ヒストグラム書いたけど右に裾が広すぎていまいちよくわからん...かといって右裾だけを拡大したグラフ書くのもなんかかっこ悪い。
- 積み上げ棒グラフ作りたいけど数が少ないやつ潰れてしまう。てかそもそもseabornで積み上げグラフめんどい。
- 散布図で外れているデータを確認したいけど、どのデータが外れているデータなのか探すのが面倒。
- ペアプロットしたけど説明変数が多すぎる...もっと一発でどの説明変数が重要なのか確かめる方法ないのか~
- 時系列データで異常が出ているときの時刻や値が知りたい。
この記事でやること
seabornと比較して便利なグラフをプロットしてみます分析データとしてpythonのデータセットのなかからtitanicのデータ、年度ごとの乗客数のデータ、ワインの等級のデータを使います。
titanicデータで
- ヒストグラム
- 積み上げ棒グラフ
- 箱ひげ図
飛行機乗客数データで
- 折れ線グラフ
ワインの等級データで
- 散布図
- 並行座標
これらのグラフについて実際のhtmlファイルへのリンクも載せました。htmlリンクからでは実際にぐりぐり動かす感じを味わえます。気持ちいいです。
例えばこちらのグラフとか。
https://nakanakana12.github.io/plotly/hello_world/histgram.html
様々なグラフの書き方はこちらの記事がめちゃくちゃ詳しいです。
令和時代のPython作図ライブラリのデファクトスタンダードPlotlyExpressの基本的な描き方まとめ https://qiita.com/hanon/items/d8cbe25aa8f3a9347b0b
ライブラリのインポート
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
from sklearn.datasets import load_wine
titanicのデータ
df = pd.read_csv('http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic3.csv')
#年齢を10歳ごとに丸めた列を追加
df["age10"] = df["age"] // 10 * 10
df["survived_num"] = df["survived"]
df["survived"] = df["survived"].replace(1,"alive").replace(0,"dead")
df["sex_num"] = df["sex"].replace("female",1).replace("male",0)
df = df.reset_index()
df.head()
ヒストグラム
右に裾が長い分布に対してはplotlyが便利!
運賃(fare)のヒストグラムを表示します。生存したかどうか(survived)で色分けしました。
運賃は正規分布となっておらず、右側に裾が長い分布となっています。
こういうときって、matplotlibだと数が少ないデータがみづらくなってけっこう困りますよね。
plotlyなら少ないところを拡大できるので様子をつかみやすいです。
今回の場合、運賃が高い人は数は少ないけど生存率が高いのが一つのグラフをぐりぐりするだけでわかりました。
fig = px.histogram(df, x="fare", color="survived",nbins=200, opacity=0.4, marginal="box"
, title="Survivedごとの運賃のヒストグラム")
fig.update_layout(barmode='overlay')
fig.show()
# htmlで保存
fig.write_html('./histogram.html', auto_open=False)
htmlファイルはこちら。グリグリ動かせます。
https://nakanakana12.github.io/plotly/hello_world/histgram.html
積み上げ棒グラフ
plotly expressなら積み上げ棒グラフが簡単で見やすい!
これが一番のおすすめかもしれないです。
積み上げ棒グラフをつくったとき困るのが、分類が多いときですよね。
数の少ないものの数がわからなかったりします。
plotlyなら数が少なくてもカーソルを合わせれば数が確認できるのは便利ですね。
ここでは年齢ごとの生存したかどうかを可視化しました。また、性別をまとめて表示した場合とグラフを分けた場合のものをつくってみました。
50代以降は生存率が低くなっていることや、女性の方が生存率が高いのが上手に可視化されていますね。
#前処理
df_bar = df.groupby(["survived", "age10","sex"],as_index=False).size().reset_index(drop=True)
df_bar.columns = ["survived", "age10","sex","count"]
df_bar.head()
fig = px.bar(df_bar, y="age10", x="count", orientation="h",color="survived"
, title="年齢ごとのsurvived(まとめて表示)")
fig.show()
htmlファイルはこちら。
https://nakanakana12.github.io/plotly/hello_world/bar.html
fig = px.bar(df_bar, y="age10", x="count", orientation="h",facet_row="sex",color="survived"
, title="年齢ごとのsurvived")
fig.show()
htmlファイルはこちら。
https://nakanakana12.github.io/plotly/hello_world/bar3.html
箱ひげ図
外れ値の確認が簡単!
箱ひげ図の場合、外れ値や信頼区間のデータを簡単に確認できるのが便利です。
また、個人的に便利だと思うのがhover_dataをindexに指定することです。
こうすることで外れ値のindexを簡単に確認でき、その他の列のデータもすぐに確認できます。
fig = px.box(df, x="pclass", y="age", color="survived", hover_data=["index"])
fig.show()
# htmlで保存
fig.write_html('./box.html', auto_open=False)
htmlファイルはこちら。
https://nakanakana12.github.io/plotly/hello_world/box.html
飛行機の乗客データ
折れ線グラフ
異常値の時刻や値が簡単にわかる!
時系列データの場合折れ線グラフが定番ですね。乗客数のデータから各月ごとの推移をプロットしてみます。
表示するグラフを凡例をクリックすることで選択できたり、下のスライダーで表示区間を選択できます。
またマウスで気になる点のx軸、y軸を確認することができます。
このデータだと正直恩恵すくないですが、カテゴリが多いときや、異常値をのx軸を確認したいときなどには便利そうです。
df = sns.load_dataset("flights")
fig = px.line(df, x="year", y="passengers", color="month", title="乗客数の推移")
fig.update_layout(xaxis_range=['1949-01-01', '1961-01-01'], # datetime.datetimeで指定してもよい
xaxis_rangeslider_visible=True)
fig.show()
# htmlで保存
fig.write_html('./time_series.html', auto_open=False)
htmlファイルはこちら。
https://nakanakana12.github.io/plotly/hello_world/time_series.html
ワインの等級データ
データの準備
data_wine = load_wine()
df = pd.DataFrame(data_wine["data"], columns=data_wine["feature_names"])
df["target_ID"] = data_wine["target"]
df["target"] = df["target_ID"].replace(0,"bad").replace(1,"good").replace(2,"great")
df["alcohol_rank"] = np.where(df["alcohol"] < df["alcohol"].mean(),"low", "high")
df["flavanoids_rank"] = np.where(df["flavanoids"] < df["flavanoids"].mean(),"low", "high")
df = df.reset_index()
df.head()
散布図
気になるデータのindexが簡単にわかる!
散布図もマウスをあてることで、どのデータが外れ値なのかを簡単に確認できるのが便利です。
個人的おすすめはhover_dataにindexを指定することですかね。これをすれば、マウスをあてるだけで外れ値のデータのindexがわかり他の値も簡単に確認することができます。
seabornのペアプロットみたいなこともけっこう簡単にできちゃいます。
fig = px.scatter(df, x="alcohol", y="color_intensity", color="target",
marginal_x="box", marginal_y="histogram", trendline="ols",
hover_data=["index"],
title="ワインのアルコール度数と色彩強度の関係")
fig.show()
# htmlで保存
fig.write_html('./scatter.html', auto_open=False)
htmlファイルはこちら。
https://nakanakana12.github.io/plotly/hello_world/scatter.html
fig = px.scatter_matrix(df, dimensions=["alcohol", "flavanoids","color_intensity","hue"],color="target",
hover_data=["index"],
title="ワインの説明変数相関分析")
fig.show()
# htmlで保存
fig.write_html('./scatter2.html', auto_open=False)

htmlファイルはこちら。
https://nakanakana12.github.io/plotly/hello_world/scatter2.html
並行座標
変数ごとの相関を確認しやすい!!
説明変数が多いときこれはめちゃくちゃ役に立ちそう。
この図を見るとflavanoidsやhueが小さいとき、color_intensityが大きいときにtarget_IDが大きくなるのが一目瞭然ですね。
他の変数の相関もかなりわかりやすい気がします。
カテゴリ化された変数にも使うことができます。
fig = px.parallel_coordinates(df, dimensions=["alcohol","flavanoids", "color_intensity","hue"],color="target_ID")
fig.show()
# htmlで保存
fig.write_html('./parallel.html', auto_open=False)
htmlファイルはこちら。
https://nakanakana12.github.io/plotly/hello_world/parallel.html
#カテゴリカル変数の場合
fig = px.parallel_categories(df, dimensions=["alcohol_rank","flavanoids_rank","target"],color="target_ID")
fig.show()
# htmlで保存
fig.write_html('./parallel_cat.html', auto_open=False)
htmlファイルはこちら。
https://nakanakana12.github.io/plotly/hello_world/parallel_cat.html
終わりに
plotly自体は知っていたのですが、使い方に癖があり学習を断念していました。
それに比べるとplotly expressはけっこう簡単に使い始められる感じです。
外れ値の確認作業などがある場合は本当に便利ですね。
3Dの可視化やアニメーションなんかもいつかチャレンジしてみたいです。
最後までお読みいただきありがとうございました。
参考になりましたらLGTMなどしてくれたら励みになります。