【Streamlit】グラフを可視化する時に使用するライブラリに悩んだら

# 前置き
こんにちはデータエンジニアの山口歩夢です！

この度、Streamlitの入門書を執筆しました！
Streamlitについて、基本的な内容から実践的な内容、自分が開発する上で躓いたポイントやTipsなどを書かせていただきました。

電子版が技術書典にて購入可能なため、是非チェックいただけると幸いです。

https://techbookfest.org/product/t5GBwbFm4kUhXrTPkGpAnY?utm_source=twitter&utm_medium=social&utm_campaign=share


# 本題
Streamlitはグラフ可視化するためのライブラリをいくつかサポートしていて、それらに対応した関数がそれぞれ用意されています。
どのライブラリ・関数を使用しようか自分自信悩んだため、今回はそちらについて記事を書いて整理してみました。

## Streamlitがサポートしているライブラリ
Streamlitでは、いくつかのグラフ可視化のためのライブラリをサポートしています。
Matplotlib、Plotly、Vega Lite、Bokeh、Altairなどです。

上記のライブラリを使用してグラフを出力するためのStreamlit関数がそれぞれ以下のように用意されています。

* `st.pyplot`: Matplotlibを出力する
* `st.altair_chart`: Altairを出力する
* `st.vega_lite_chart`: Vega Liteを出力する
* `st.plotly_chart`: Plotlyを出力する
* `st.bokeh_chart`: Bokehを出力する

どれを使ってグラフを可視化しようか悩んだので、色々と調査をしてみました。




## 結論
面グラフ、棒グラフ、折れ線グラフ、散布図であれば、以下の関数を使用します。
こちらは、`st.altair_chart`を簡単にコードを書けるようにした関数(syntax-sugarと呼ばれる関数)です。
シンプルなグラフであれば、以下の関数でとても簡単に可視化することができます。

* `st.area_chart`
* `st.bar_chart`
* `st.line_chart`
* `st.scattar_chart`

そして、上記のグラフ以外を可視化する場合(例：円グラフ、集合棒グラフなど)は、
以下のようにplotlyとaltairのサンプル集があるので、そちらを見てどちらのライブラリを使えばやりたいことができそうか考えればいいのかなと思いました。
(もちろん、明確に使いたいライブラリが決まっている場合は、そちらを使用します。)

https://plotly.streamlit.app/Bubble_Charts

https://altair.streamlit.app/

## しっかり検討したい場合
結論で書いた通り、上記のサンプル集を見て作りたいグラフを探し、データ可視化アプリを作るのがいいと思います。
しかし、Streamlitでのデータ可視化に慣れてきたら、それぞれのライブラリの長所をしっかり活かしたアプリを作りたくなるかなと思いました。

そのため、Streamlitでサポートしているデータ可視化ライブラリの特徴を調査してみました！

### Matplotlib
* 歴史が長く安定している
  * 2003年に初回版がリリースされ、非常に多くのドキュメントや例がある
* 柔軟性が高い
    * 細部までカスタマイズ可能で、複雑なグラフも作成可能
* 静的グラフ向け

複雑なカスタマイズが必要な場合や、学術論文やレポート用の静的グラフを作成する場合に使われることが多いようです。
Matplotlibは以下のようなイメージになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/883573/0b299f13-b79d-847d-3099-9abd0b29020a.png)


### Altair / Vega-Lite

* シンプルな文法
    * コードがシンプルで読みやすい。グラフの構造を宣言的に定義するため、理解しやすい
* 統計的プロットに強い
    * データ変換や集約、統計的な視覚化が容易
* インタラクティブな操作が可能

簡単かつ迅速に美しいグラフを作成したい場合や、インタラクティブなデータ探索が必要な場合に使われます。
Altairは、以下のようなイメージになります。
そして、右上のメニューからSVGやPNGとしてグラフを出力したり、グラフの上にカーソルを置くことで値を表示することも可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/883573/886813d1-7933-681e-d833-eacdf7b8c915.png)



### Plotly
* 高機能なインタラクティブ性
    * ズーム、パンなどのインタラクティブ機能が非常に充実している
    * 要素をクリックしてイベントをトリガーすることも可能
* 豊富なグラフ種類
    * 折れ線グラフ、棒グラフ、円グラフなどの基本的なグラフから、3Dグラフや地理的なマップ、ヒートマップなど、多彩なグラフを簡単に作成可能

matplotlibが高い精度で静的で複雑なプロットを作成するのに対して、高度なインタラクティブ性が求められる場合に向いています。

Plotlyは以下のようなイメージになります。
PlotlyもAltairと同様に右上のメニューからPNGとしてグラフを出力したりズームしたり、グラフの上にカーソルを置くことで値を表示することも可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/883573/f163a9cf-aed0-d4ad-8417-9a2e6bd4072b.png)

**AltairとPlotlyがよく似ているなと感じましたが、Plotlyはグラフにズームして、カーソルで移動できたりと、インタラクティブ性が高く操作できるところが違いかなと感じました。**


### Bokeh
* 高いカスタマイズ性
    * 複雑なグラフやインタラクティブ要素のカスタマイズが容易
* サーバーサイドインタラクティブ性
    * Bokehサーバーを使えば、リアルタイムのデータ更新やユーザー入力に応じたインタラクティブグラフが作成可能

**リアルタイムデータの可視化が必要**な場合に、こちらのライブラリの使用を検討すると良さそうです。
Bokehのイメージは以下になります。
右側のメニューからズームアップ・ズームアウト・軸の調整などが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/883573/028a4f5b-b637-548d-50f8-02bd3d1aa598.png)


### その他の検討材料

`st.plotly_chart`、`st.altair_chart`、`st.vega_lite_chart`では、Chart Selectionという機能が使えます。
そちらを検討材料に入れるのもいいかと思いました。以下にサンプルアプリケーションを添付します。

https://chart-selections-demo.streamlit.app/Plotly

グラフのクリックした箇所を辞書型で出力してくれていますね。
クリックした箇所をデータフレームなどで綺麗に出力したり、加工を加えることでもっと高度な機能を実装できそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/883573/9a772820-3c31-065b-e8ae-db8c05f705a0.png)


# まとめ
簡単にまとめると以下のような使い分けになるのかなと思いました！
自分は見た目が好きなので、Altairをよく使用しています。

* 静的で高精度なグラフはMatplotlib
* シンプルで宣言的なコード、統計的な視覚化、インタラクティブな操作がしたい場合はAltair / Vega-Lite
* Altairよりさらに高度なインタラクティブ操作がしたい場合はPlotly
* リアルタイムデータ対応はBokeh