Webアプリ作成 -Streamlit⑤-
今回はDataFrameやグラフの表示についてです。
DataFrameの表示
DataFrameをそのままwebアプリ上に表示させることができます。やり方は簡単で、st.dataframe()で表示させることができます。
例として、Altairの解説で使用したdfを使用します。元データのcsvファイルは、同じディレクトリに保存してファイル名(相対パス)で読み込んでいます。
下記コードをpyファイルとして保存し(ここではsample.py)、ターミナルで「streamlit run sample.py」と入力するとlocalhostで表示されます。この時、ターミナルはpyファイルを保存したディレクトリであることに注意してください(異なる場合は、cdコマンドで移動が必要です!)。詳細は以前の投稿をご覧ください。
import streamlit as st
import pandas as pd
# ファイルの読み込み
df = pd.read_csv('newly_confirmed_cases_per_100_thousand_population_daily.csv')
# データフレームの整形
df['Date'] = pd.to_datetime(df['Date'])
df = df[['Date', 'Hokkaido', 'Tokyo', 'Osaka', 'Okinawa']]
df.rename(columns={'Date': '年月日',
'Hokkaido': '北海道',
'Tokyo': '東京',
'Osaka': '大阪',
'Okinawa': '沖縄'},
inplace=True
)
df.set_index('年月日', inplace=True)
st.dataframe(df)
ブラウザ上にdfを表示することができました。indexの日付や各都道府県をクリックすると昇順・降順を変えることができます。
df.style.highlight_max()とすることで最大値をハイライトすることもできます。maxの部分をminやbetweenにすることでハイライトする条件を変えることもできます。また、widthやheightで表示するdfサイズを指定することもできます。
st.dataframe(df.style.highlight_max(axis=0), width=600, height=500)
使用しているデータは、厚労省が公開している人口10万人当たりの新型コロナウイルス新規陽性者数ですが、2年前あたりがピークだったようです。最近また増え始めているようですので皆さんもご注意ください。
st.dataframe(df.style.highlight_between(axis=0, left=50, right=100), width=600, height=500)
dfを単純にテーブル(表)として表示することもできます。
st.table(df)
グラフの表示
書き方
グラフの表示も簡単にできます。matplotlibのグラフはst.pyplot()、altairのグラフはst.altair_chart()で表示できます。
インタラクティブなアプリに仕上げる
先ほどのdfには北海道、東京、大阪および沖縄の4都道府県のデータが含まれています。この中から見たいデータだけを選んで表示させるインタラクティブなwebアプリにしてみましょう。
作図のコードは上記リンクのコードをベースにします。
4都道府県から1つ以上を選択するので、st.multiselect(label, options)を使用します。引数のoptionsには、選択肢をリストなどの形式で渡します。["北海道", "東京", "大阪", "沖縄"]のように直接的なリストを作成しても良いですが、元データを変えるたびにリストもメンテナンスする必要があるため面倒です。
options = df_melt['都道府県'].unique().tolist()
df_meltの"都道府県"列に含まれるデータがリストの構成要素なので、"都道府県"列のデータから重複を削除し(unique())、リスト化(tolist())すれば、optionsのリストメンテナンスは不要になります。
st.multiselect()で選択した結果は、リストとして返されるので適当な変数に格納しておきます。
prefs = st.multiselect('都道府県を選択', options)
あとは、全体のデータ(df_melt)から選択された都道府県のみを抽出し、altair用のソースデータとすれば作図できます。multiselect()で選択した後に作図のGoサインを出すボタンを作っておくとアプリっぽくなります。
import streamlit as st
import pandas as pd
import altair as alt
# ファイルの読み込み
df = pd.read_csv('newly_confirmed_cases_per_100_thousand_population_daily.csv')
# データフレームの整形
df['Date'] = pd.to_datetime(df['Date'])
df = df[['Date', 'Hokkaido', 'Tokyo', 'Osaka', 'Okinawa']]
df.rename(columns={'Date': '年月日',
'Hokkaido': '北海道',
'Tokyo': '東京',
'Osaka': '大阪',
'Okinawa': '沖縄'},
inplace=True
)
# Altair用にmelt
df_melt = pd.melt(df, id_vars='年月日', var_name='都道府県', value_name='陽性者数')
# 表示する都道府県を選択
options = df_melt['都道府県'].unique().tolist()
prefs = st.multiselect('都道府県を選択', options)
btn = st.button('表示')
if btn:
df_q = df_melt.query('都道府県 in @prefs')
chart = alt.Chart(df_q).mark_area().encode(
x="年月日:T",
y="陽性者数:Q",
color="都道府県:N",
row=alt.Row("都道府県:N"),
).properties(height=200, width=400
)
st.altair_chart(chart)
# 表示用にdfを加工(選択された都道府県のみに)
df.set_index('年月日', inplace=True)
df_select = df[prefs]
st.dataframe(df_select.style.highlight_max(axis=0),
width=150*len(options), height=300)
最後の行で表示するdfの横幅をwidth=150*len(options)として、選択された都道府県の数に応じて幅が変わるようにしています。こうすることで、1つのみ選択された場合でも全て選択された場合でも見栄え良く表示することができます。
これまで紹介してきたウィジェットと組み合わせることで欲しいデータだけを可視化するようなwebアプリをサクッと作れてしまいます。めちゃくちゃ便利!