streamlitの使い方/基本機能を解説【Pythonでシンプルなwebブラウザアプリを作成する方法】株価ダッシュボードのサンプルコードあり
目次
こんにちは。
今年の3月にstreamlitを使ってみる記事を書いたのですが、この1年で急激にバージョンアップして更に使いやすくなった感があります。
今回の記事は、個人的に特によく使いそうな機能をまとめてみました。
また、最後に株価取得して表示するダッシュボードも作ってみます。サンプルコードもありますので、ぜひご参考に。
この記事を読めば、↑このような画面構成の株価時系列データを表示するwebアプリケーションが簡単に作れるようになります。よろしく。
動作確認した環境
- Python
- 3.10.1
- streamlit
- 1.3.0
- VS Code
- 1.63.2
- MacOS
- Monterey 12.0.1
Pythonのインストールとバージョンアップ方法はこちらの記事をご参考に。
MacOSでPython3.10にバージョンアップ/インストールする方法【仮想環境で使う方法も解説】Homebrewでトライすると...
streamlitのインストールと実行方法
詳細は前回の記事と同じです。仮想環境で使う方法もまとめています。
インストールコマンド
$ pip install streamlit
Pythonプログラム内でのインポート
import streamlit as st
# 以降プログラムを記述する。
streamlitアプリケーションの実行方法
$ streamlit hello # サンプルの実行
$ streamlit run hoge.py # 自作したpythonファイルhoge.pyの実行
localhost:8501
でアプリケーションが起動しますので、webブラウザでアクセスして確認できます。
終了はcontrol + C
。
streamlitの機能1. テーブル、値の表示 【DataFrame/Table/Metric】
データフレーム(pandas.DataFrame)の表示
st.dataframe(data=None, width=None, height=None)
# 例
st.dataframe(df, 500, 100)
width
とheight
はintでpixelを指定します。
テーブルの表示
st.table(df)
# 例
st.table(df.head(3))
データフレームとの違いは、データ全体が固定表示される点。
大量のデータを表示する場合はst.dataframe
の方が良さそうです。高さ・幅を指定して、中身はスクロールで表示されます。
メトリック(測定基準、数値)の表示
st.metric(label, value, delta=None, delta_color="normal")
# 例
st.metric('Metric', '100', delta='-1.0', delta_color='normal')
value
やdelta
はintだけでなくstrも使えます。
deltacolor
は以下
normal
: 正ならgreen, 負なら赤inverse
: normalの逆off
: 常にgray
ここまでの例を実行するとこんな感じ。st.title('Title')
でタイトルがつけられます。
データは以下のようなランダム値の2列30行のデータフレームを使っています。
array = np.random.randn(30,2) * [100, 100]
df = pd.DataFrame(array,columns=['A', 'B'])
streamlitの機能2. グラフ、チャートの表示 【折れ線、棒、Matplotlib】
折れ線グラフ
st.line_chart(data=None, width=0, height=0, use_container_width=True)
# 例
st.line_chart(df, 400,200)
width
とheight
は描画エリアのpixelサイズです。0(default)なら自動。
棒グラフ
st.bar_chart(data=None, width=0, height=0, use_container_width=True)
# 例
st.bar_chart(df, 400,200)
引数については同上。
塗りつぶし折れ線グラフ(エリアチャート)
st.area_chart(data=None, width=0, height=0, use_container_width=True)
# 例
st.area_chart(df, 400, 200)
chartの例はこんな感じ。
他の可視化ライブラリを利用 Matplotlibなど
# matplotlib
st.pyplot(fig=None, clear_figure=None, **kwargs)
# altair
st.altair_chart(altair_chart, use_container_width=False)
# vega_lite
st.vega_lite_chart(data=None, spec=None, use_container_width=False, **kwargs)
# plotly
st.plotly_chart(figure_or_data, use_container_width=False, sharing="streamlit", **kwargs)
matplotlibがよく使われそう。
# 例
import matplotlib.pyplot as plt
fig,ax = plt.subplots(1,1,figsize=(4,2))
ax.hist(df.A, bins=20)
st.pyplot(fig)
streamlitの機能2. 入力ウィジェットの作成 【ボタン、ドロップダウン、テキストエリア等】
豊富な入力ウィジェットたち。どれも一行で実現可能。簡単すぎる。
# ボタン
st.button(label, key=None, help=None, on_click=None, args=None, kwargs=None)
# ダウンロードボタン
st.download_button(label, data, file_name=None, mime=None, key=None, help=None, on_click=None, args=None, kwargs=None)
# チェックボックス
st.checkbox(label, value=False, key=None, help=None, on_change=None, args=None, kwargs=None)
# ラジオボタン
st.radio(label, options, index=0, format_func=special_internal_function, key=None, help=None, on_change=None, args=None, kwargs=None)
# セレクトボックス
st.selectbox(label, options, index=0, format_func=special_internal_function, key=None, help=None, on_change=None, args=None, kwargs=None)
# マルチセレクト
st.multiselect(label, options, default=None, format_func=special_internal_function, key=None, help=None, on_change=None, args=None, kwargs=None)
# スライダー
st.slider(label, min_value=None, max_value=None, value=None, step=None, format=None, key=None, help=None, on_change=None, args=None, kwargs=None)
# セレクトスライダー
st.select_slider(label, options=[], value=None, format_func=special_internal_function, key=None, help=None, on_change=None, args=None, kwargs=None)
# テキストボックス
st.text_input(label, value="", max_chars=None, key=None, type="default", help=None, autocomplete=None, on_change=None, args=None, kwargs=None, *, placeholder=None)
# 数値入力
st.number_input(label, min_value=None, max_value=None, value=, step=None, format=None, key=None, help=None, on_change=None, args=None, kwargs=None)
# テキストエリア
st.text_area(label, value="", height=None, max_chars=None, key=None, help=None, on_change=None, args=None, kwargs=None, *, placeholder=None)
# 日付入力(カレンダー入力)
st.date_input(label, value=None, min_value=None, max_value=None, key=None, help=None, on_change=None, args=None, kwargs=None)
# 時刻入力
st.time_input(label, value=None, key=None, help=None, on_change=None, args=None, kwargs=None)
# ファイルアップロード (200MBまで)
st.file_uploader(label, type=None, accept_multiple_files=False, key=None, help=None, on_change=None, args=None, kwargs=None)
# カラーピッカー
st.color_picker(label, value=None, key=None, help=None, on_change=None, args=None, kwargs=None)
入力ウィジェットの使い方
例えば、以下のボタンを置くだけで、押すと画面が再読込(リロード)されるので、上の例で使ったようなランダム値のデータは更新されます。
st.button('Click!', on_click=None)
以下のボタンを押すと、pressed
と画面に表示されます。押すとパラメータを更新するなどの動作は、このifブロックの中に書けばよさそう。
if st.button('Press'):
st.write('pressed')
セレクトボックスとマルチセレクトあたりもパラメータを渡すのによく使いそう。
options=['option1','option2','option3']
# セレクトボックス
st.selectbox('selectbox', options, index=2) # 0番から数えて2番の要素がデフオルトになる
# マルチセレクト
st.multiselect('multiselect', options)
セレクトボックスで選択した値を画面に表示するには以下のように記載します。
def echo_params():
st.text(st.session_state.select1)
options = ['A','B','C','D','E']
st.selectbox(
'update parameter',
options, key='select1', on_change=echo_params)
簡単に解説。st.session_state
には、ウィジェットからkey
で渡した名前で呼び出せる変数に値が保持されます。(ウィジェットに何か入力されると、同一セッション内で一時的に保持されます。) 引数on_change
はコールバックと言って、ウィジェットに入力された値が変化したときに関数を呼び出します。
つまり、以下のような流れになっています。
- ウィジェット(今回はセレクトボックス)で値を選択(入力)する
- ウィジェットの
key
で指定した名前で、session_state
にウィジェット入力した値が保持される。 on_change
で関数を呼び出す- 呼び出した関数の中で、
session_state
から値を取り出す - 呼び出した関数の中で、取り出した値を画面に描画する
この仕組みを使って、on_change
で呼び出す関数の中にグラフを入れておけば、「ドロップダウンで選択した値をパラメータにしたグラフを描く」といったことも可能です。
例えば、以下のコードは「1~10の値をとるスライダーで、選択した数値の行数のテーブルを表示する」といった動作を実現します。
def echo_table():
n = st.session_state.slider1
st.table(df.head(n))
st.slider(
'head row number',
min_value=1, max_value=10, step=1,
key='slider1', on_change= echo_table)
このように、書き換えたいグラフやテーブルは関数の中に実装していく形になりそうですね。
他のウィジェットも同様に、key
とon_change
、st.session_state
を使えば色々できそうです。
streamlitの機能3. 画面レイアウト 【サイドバー、カラム、コンテナ】
サイドバー
st.sidebar.[element_name]
という形式でサイドバーにウィジェットを追加できる。
st.sidebar.button('Click!')
st.sidebar.text_area('text area', value='hogehoge')
カラム
Pythonファイルに普通に要素を書いていくとページに縦に並んでいきます。横に並ばせたいときはst.columns
を使います。
col1, col2 = st.columns([2,1])
with col1:
st.header('Table')
st.table(df.head(5))
with col2:
st.header('Metric')
st.metric('Metric', '100', delta='-1.0', delta_color='normal')
st.header('Line chart')
st.line_chart(df, width=0, height=200)
これでレイアウトも自由自在。
エキスパンダー(expander)
クリックすると開いたり閉じたりする。常に見せておくことはないけど、たまに必要になる情報の記載に便利。
with st.expander(label):
# 中身
streamlitの機能4. テキスト表現色々 【タイトル、サブタイトル、コード、数式等】
今までも少し出てきましたが、タイトルだけでなく色々なテキスト表現が可能です。
st.markdown('**マークダウン**形式です。')
st.title('タイトル')
st.header('ヘッダー')
st.subheader('サブヘッダー')
st.caption('キャプション 文字サイズ小')
st.code('import streamlit as st', language='python')
st.text('これはテキストです。')
st.latex('\sum_{k=0}^{n-1} ar^k') # LaTeX形式
【実践編】 streamlitで株価ダッシュボードを作ってみる
それでは以上の機能を使った実践編として、株価ダッシュボードを作ってみます。
株価を取得するAPIについてはこちらの記事をご参照。
Yahoo!ファイナンスから複数社の株価時系列データをCSV形式でダウンロード取得し可視化する方法【Python/サンプルコード】
直近10日間について、GAFAM5社の株価の推移と、個別の推移を並べて表示するアプリケーションを作ってみます。データを読み込む関数load_data()
の解説は上記の記事内に書いてあります。
import streamlit as st
import datetime as dt
import pandas as pd
import pandas_datareader.data as web
GAFAM_SYMBOLS = ['AAPL','AMZN','GOOG','FB','MSFT'] # シンボル(ティッカー)のリストを作成
today = dt.date.today() # 今日の日付
n = 10
n_days_ago = today - dt.timedelta(days=n) # n日前の日付
@st.cache
def load_data(start,end):
data_list = [
web.DataReader(s, 'yahoo', start, end)
for s in GAFAM_SYMBOLS # リストから1社ずつ株価データをロード
]
df = pd.DataFrame(
{name: data_list[i].Close for i,name in enumerate(GAFAM_SYMBOLS)} # ロードしたデータを使って、シンボルが列名、値が終値(Close)のデータフレームを作成
)
return df
df = load_data(n_days_ago,today) # n日前から今日までのデータをロード
def echo_solo_chart():
selected_ticker = st.session_state.select1 # セレクトボックスで選択したティッカーを保持
st.header(f'{selected_ticker}')
st.line_chart(df[selected_ticker],height=200) # 選択したティッカー単体データの折れ線グラフ
return selected_ticker
def display_charts():
st.header('GAFAM') # ヘッダータイトル
st.line_chart(df,height=200) # データフレーム全体(GAFAM5社分)の折れ線グラフを表示
echo_solo_chart() # 単体の折れ線グラフを表示
with st.expander('Show Raw Data'):
st.dataframe(df) # 生データのテーブルを表示
st.sidebar.selectbox( # ティッカーを選択するセレクトボックス
'TICKER', GAFAM_SYMBOLS,
key='select1', on_change=echo_solo_chart
)
st.sidebar.date_input('start', value=n_days_ago) # ダミーです。
st.sidebar.date_input('end', value=today) # ダミーです。
display_charts()
関数の前に@st.cache
というデコレータをつけるとキャッシュ機能が働き、データのロードが最初の1回ですみます。これがないと、セレクトボックスで値を選択するたびにデータの読み込み処理が走ってとても時間がかかります。
st.sidebar.selectbox(...)
で選択した値はecho_solo_chart()
関数に渡して、ドロップダウンで選択したシンボルの株価チャートを表示するようにしました。
expander
を使って生データのテーブル表示/非表示を切り替えられるようにしました。
実行すると、このような画面になりました。↓
日付入力部分は見た目をそれっぽくするためのダミーです。on_change
でコールバックすれば選択した期間のデータを表示することも可能です。ぜひお試しあれ。(期間が長いとデータのロードに時間がかかるので注意です)
まとめ
というわけで今回はstreamlitの基本機能をまとめてみて、試しに株価ダッシュボードを作成してみました。
Pythonのシンプルなコードで簡単にwebブラウザアプリケーションを自作できるstreamlit。今後の機能追加にも期待です。
それでは〜。
参考ドキュメント
今回は基本的なよく使う機能を中心にまとめてみましたが、他にもメディア再生、プログレスバーの表示、エラー警告・例外処理など、streamlitでは色々な機能が提供されています。もっと深く使ってみたい方は公式のAPIリファレンスをご参考に。