Streamlitに入門してみる

# はじめに
こんにちは、こんばんは、_hyoheiです。タイトルに記載の通り本記事ではStreamlitに入門します。以下の構成でStreamlitがどのようなフレームワークであるか概観することを目的とします。

1. Streamlitの概要
2. 基本的なAPIをいくつか触ってみる

# Streamlitとは
2019年10月にローンチされた機械学習およびデータサイエンスのためのWebアプリケーションフレームです。[^1] Pythonスクリプトのみでフロントエンドアプリケーションを構築でき、分析結果や定常的なグラフデータの可視化などがWebアプリ上で短時間で実現できます。フロントエンドスタックに精通していない機械学習エンジニアやデータサイエンティストにとって、学習コストを最小限に抑えつつ簡易に可視化アプリケーションを作成できるメリットがあります。

**本家URL**
https://www.streamlit.io/

### インストール
Python3.6~3.8がインストール済みの状態で、以下pipコマンドをターミナル上で叩くことでインストール出来ます。

```
$ pip install streamlit
```

### Webアプリケーション起動
StreamlitではPythonスクリプトを実行するかのように、特定のPythonスクリプトを指定した状態で以下コマンドを叩くだけでWebアプリケーションが起動出来ます。

```first_app.py
# streamlitをインポートするだけのPythonスクリプト
import streamlit as st
```

```
# ターミナルで以下コマンド叩きWebアプリケーション起動
$ streamlit run first_app.py
```

コマンドを叩き以下の結果が標準出力されれば正常に起動出来ています。

```
  You can now view your Streamlit app in your browser.

  Local URL: http://localhost:8501
  Network URL: http://xxx.xxx.xx.xxx:xxxx
```

上記ローカルホストされているURLにブラウザからアクセスすると（何も表示はないですが）正常にアプリケーションが起動していることがクライアント側からも確認出来ます。とても簡単ですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115275/9358a3ad-6f18-7001-23c7-aebdd0458e41.png)


# 基本的なAPIをいくつか触ってみる
ここからはStreamlitの基本的なAPIを紹介し、どのような機能があるか確認して行きたいと思います。

### タイトルの表示
`st.title`を利用してアプリケーションのタイトルを定義します。

```first_app_with_title.py
import streamlit as st

st.title('My first app')
```

実行結果は以下となります。画面上にh1要素のタイトルが表示されたことが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115275/11359d82-271b-a6e0-bd08-2edb4619bf72.png)

### DataFrameの表示
表データの可視化はPandasのDataFrameを用いて行います。[^2] `st.write`を利用してDataFrameを表示します。

```first_app_with_dataframe.py
import streamlit as st
import pandas as pd

st.title('My first app')

df = pd.DataFrame({
     'first column': [1, 2, 3, 4],
     'second column': [10, 20, 30, 40]
     })
st.write(df)
```

実行結果は以下となります。データフレームの内容がそのまま画面に表示されてることが確認できます。またカラムヘッダー部分をクリックすると昇順降順を変更することが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115275/d645d335-ceb1-4609-4d65-c0fe32c81536.png)

### 折れ線グラフの表示
`st.line_chart()`を利用して折れ線グラフを表示します。引数に渡すデータ構造はそれぞれのカラムが1つの線分の連続的な値を保持するDataFrameです。今回はNumpyを用いて3つの線分用にランダムな値を20個生成しています。

```first_app_with_line_chart.py
import streamlit as st
import numpy as np
import pandas as pd

st.title('My first app')

chart_data = pd.DataFrame(
     np.random.randn(20, 3),
     columns=['a', 'b', 'c']
 )
st.line_chart(chart_data)
```

実行は以下となります。描画したグラフはSVGやPNGなどの画像データとして保存することが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115275/b719e9d6-82ce-e48b-396d-05c4b9758d12.png)

### 地図データと特定のデータポイントの表示
`st.map()`を利用して地図データを表示します。引数に渡すDataFrameは1列目を緯度、2列目を経度として定義することで、その地点を地図上にプロットします。今回は東京を基準としてその周辺にランダムに500個の地点をプロットしています。

```first_app_with_map.py
import streamlit as st
import numpy as np
import pandas as pd

st.title('My first app')

map_data = pd.DataFrame(
    np.random.randn(500, 2) / [50, 50] + [35.7, 139.67],
    columns=['lat', 'lon']
)
st.map(map_data)
```

実行結果は以下となります。今回のプロットデータに特に意味はないです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115275/bfb347e4-e88b-e73e-9811-6e9dd9e10009.png)

### チェックボックスによるデータの表示/非表示選択
`st.checkbox`を利用してデータの表示/非表示を行います。引数にはチェックボックスに表示するテキストを渡します。

```first_app_with_checkbox.py
import streamlit as st
import numpy as np
import pandas as pd

st.title('My first app')

if st.checkbox('Show dataframe'):
    chart_data = pd.DataFrame(
        np.random.randn(20, 3),
        columns=['a', 'b', 'c']
    )
    st.line_chart(chart_data)
```

実行結果は以下となります。
![checkbox.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115275/f1494595-1d00-b51f-39df-669713efef8b.gif)

### セレクトボックスの利用
`st.selectbox`を利用してセレクトボックスを表示します。第1引数には文字列、第2引数には選択肢を保持するSeriesデータを指定します。

```first_app_with_selectbox.py
import streamlit as st
import pandas as pd

st.title('My first app')

df = pd.DataFrame({
     'first column': [1, 2, 3, 4],
     })

option = st.selectbox(
    'Which number do you like best?',
    df['first column']
)
st.write('You selected: ', option)
```

実行結果は以下となります。
![selectbox.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115275/c79c1632-599c-1282-e874-e4980aa6d391.gif)

### プログレスバーの表示
`st.progress`を利用しプログレスバーを表示します。長時間の計算が必要なアプリケーションの場合、プログレスバーを利用することでリアルタイムでステータスを確認することが出来ます。

```first_app_with_progressbar.py
import streamlit as st
import time

st.title('My first app')

st.write('Starting a long computation...')

latest_iteration = st.empty()
bar = st.progress(0)

for i in range(100):
    latest_iteration.text(f'Iteration {i+1}')
    bar.progress(i+1)
    time.sleep(0.1)

st.write('...and now we\'re done!')
```

実行結果は以下となります。
![progressbar.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115275/4bf41f00-7708-d058-95ec-c5f8fa81ad8f.gif)

# まとめ
かなり基本的なAPIのみの紹介でしたが、とても少ないコード記述量でフロントエンドアプリケーションが記述できることがなんとなくお分かりいただけたかと思います。ExcelやJupyterNotebookで分析結果を可視化するだけで十分なユースケースではWebアプリケーションを構築するメリットはあまりないかと思いますが、リアルタイムに変化するデータをダッシュボード上で確認したいといったような要件にはこのStreamlitが非常に強力なフレームワークとして機能するかと思います。まだまだ盛んに開発が継続されているフレームワークなので今後どのような進化を遂げていくのか注目です。

[^1]: https://towardsdatascience.com/coding-ml-tools-like-you-code-ml-models-ddba3357eace
[^2]: 実際のユースケースあればDBやcsvなどの外部データからDataFrameとしてロードすることが想定されますが、今回は簡単のためにスクリプト内にデータをベタ書きをしています。