【Python】Streamlitに入門してみた
背景
前回携わったプロジェクトで全球(地球全体)規模のデータを扱うことが多々あったのでPythonやRでそれらデータの時系列推移や統計値を算出、matplotlibを使って可視化を行っていましたが見た目がダサいという欠点がありました。また、流行中のOpenAI APIを使用する際もCUIの枠を出ないとイマイチ格好良くないといった背景から今回はPythonで簡単にWebアプリが作れるStreamlitに触れてみようと思います。
Streamlitとは
StreamlitとはPythonでWebアプリを作成できるフレームワークの一つでDjangoやFlask(別のフレームワーク)ほど機能が豊富ではないものの学習コストが低く、データの可視化や表の扱いに優れているため機械学習やデータサイエンスの分野でとりあえず画面を付けてみたい場合やモックレベルでWebアプリを作成する場合によく使われているようです。
公式HP:https://streamlit.io/
実際に使ってみる
Streamlitのインストール
執筆時の環境は以下の通りです。
OS:Windows 10
Python:3.10.5
Streamlit:1.24.0
> pip install streamlit
ハロワしてみる
任意のファイル名で.pyファイルを作成(今回はhello.pyを作成)し、ファイル内に以下の記述を行いました。
先頭行でstreamlitをimportした後、streamlitの機能を使ってテキストやボタンを出してみました。
API Reference:https://docs.streamlit.io/library/api-reference
import streamlit as st
st.title("Hello world!!")
st.header("header")
st.write("text write")
st.button("ボタン")
st.selectbox("select", ("sel1", "sel2"))
st.multiselect("multiselect", ("sel1", "sel2"))
st.radio("radio", ("あいうえお", "かきくけこ"))
st.text_input("テキストボックス")
st.text_area("テキストエリア")
st.slider("スライダー", 0, 10, 5)
ここまで記載したらファイルを保存し、ターミナル上で以下コマンドを実行します。
> streamlit run hello.py
すると以下のような表示が出てくるのでアクセスしてみましょう。
You can now view your Streamlit app in your browser.
Local URL: http://localhost:8501
Network URL: http://192.168.0.106:8501
それっぽい画面に飛びました!HTMLでのWeb作成経験がある人からするとコードもスッキリしていてWebも見た目も綺麗に見えるのではないでしょうか。

データを表形式で出力してみた
今回の本題①、データの可視化を試してみます。まずは表出力をしてみます。使用するデータは乱数で100列100行のデータを作成しています。
import streamlit as st
import pandas as pd
import numpy as np
# 使用するデータを準備する(100x100の乱数)
df = pd.DataFrame(np.random.rand(100,100))
# 通常の表出力
st.header("100×100の表出力")
st.dataframe(df)
# カスタム表出力
st.header("100×100の表出力(列毎の最小値を強調)")
st.dataframe(df.style.highlight_min(axis=0,color='red'))
実行結果は以下の通り。こういった表形式のデータだとExcelに貼りなおして数式仕込んで強調表示を行っていましたが、Pythonの中で完結出来るのはとてもありがたいですね。

なんならソートも出来ました。

データをグラフで出力してみた
表同様にグラフも試してみる。先ほど同様に乱数でデータを準備(今回はグラフなのでひとまず20×4程度で)して出力してみた。
import streamlit as st
import pandas as pd
import numpy as np
# 使用するデータを準備する(20x4の乱数)
df = pd.DataFrame(np.random.rand(20,4))
# 折れ線グラフ
st.header("折れ線グラフ")
st.line_chart(df)
# 面グラフ
st.header("面グラフ")
st.area_chart(df)
比較的見やすいデザインで出力されました。モノとしてはExcelで作れそうなレベルではありますが、前述の通りPython一本で出来るのは楽ですね!

地図と組み合わせて出力してみた
Streamlitでは外部ツールとも連携しているようで、地図ツールのfoliumもStreamlit版があるようなのでこちらを使ってみます。
ひとまずstreamlit-foliumを取得。
> pip install streamlit-folium
今回も乱数を使ってデータを準備しますが、少し実業務に寄せてみます。値、経度、緯度のdataframeを作成し、値が最も大きかった座標に対してピンを立ててみます。基準座標は東京にしてみました。
import streamlit as st
import folium
from streamlit_folium import folium_static
import pandas as pd
import numpy as np
# 使用するデータを準備する
df = pd.DataFrame(
np.random.randn(100, 3) + [0, 35.6894, 139.6917],
columns=['value', 'lon', 'lat'])
# 作成した乱数の中から値が最も大きい座標にピンを立てる
st.header("特定位置にピンを立てる")
# 地図表示する際の中心座標を指定
map = folium.Map(location=[35.6894, 139.6917], zoom_start=7)
# 最大値となる緯度経度を取得
maxpoint = df.loc[[df['value'].idxmax()]]
# ピンを立てる位置を設定
folium.Marker(
location=[maxpoint.lon, maxpoint.lat],
popup="特異点"
).add_to(map)
# 地図出力
folium_static(map)
実行結果は以下のようになりました。例えば値=人口増加量であった場合、Excelで進めた場合には人口増加量が多かった緯度経度座標を把握することは出来ても、具体的には何県なの?といった部分はもう一歩踏み込む必要がありましたが、Streamlitを活用すれば全て一括で確認できそうですね!

使ってみた感想
今回はStreamlitを使用して表やグラフを出力してみましたが、コレが無いと困る!というフレームワークではないものの、あまり手間を掛けずにデータを視覚的情報として得られるのは非常に便利だと感じました。データを集計してそのまま可視化出来るのであれば異常値やデータの傾向も掴みやすいのではないでしょうか。次にStreamlitを使用する際はOpen AIと組み合わせてみたいなと思います。