streamlitの使い方/基本機能を解説【Pythonでシンプルなwebブラウザアプリを作成する方法】株価ダッシュボードのサンプルコードあり

2021-12-28
Main Image

目次

こんにちは。

今年の3月にstreamlitを使ってみる記事を書いたのですが、この1年で急激にバージョンアップして更に使いやすくなった感があります。

今回の記事は、個人的に特によく使いそうな機能をまとめてみました。

また、最後に株価取得して表示するダッシュボードも作ってみます。サンプルコードもありますので、ぜひご参考に。

streamlit sample dashboard

この記事を読めば、↑このような画面構成の株価時系列データを表示する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)

widthheightは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')

valuedeltaはintだけでなくstrも使えます。

deltacolorは以下

  • normal : 正ならgreen, 負なら赤
  • inverse : normalの逆
  • off : 常にgray

ここまでの例を実行するとこんな感じ。st.title('Title')でタイトルがつけられます。

streamlit sample

データは以下のようなランダム値の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)

widthheightは描画エリアの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の例はこんな感じ。

streamlit charts

他の可視化ライブラリを利用 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 matplotlib

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)
streamlit sample input widget

セレクトボックスで選択した値を画面に表示するには以下のように記載します。

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)

このように、書き換えたいグラフやテーブルは関数の中に実装していく形になりそうですね。

他のウィジェットも同様に、keyon_changest.session_stateを使えば色々できそうです。

streamlitの機能3. 画面レイアウト 【サイドバー、カラム、コンテナ】

サイドバー

st.sidebar.[element_name]という形式でサイドバーにウィジェットを追加できる。

st.sidebar.button('Click!')
st.sidebar.text_area('text area', value='hogehoge')
streamlit sample sidebar

カラム

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)

これでレイアウトも自由自在。

streamlit sample columns

エキスパンダー(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 sample text

【実践編】 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を使って生データのテーブル表示/非表示を切り替えられるようにしました。

実行すると、このような画面になりました。↓

streamlit sample dashboard

日付入力部分は見た目をそれっぽくするためのダミーです。on_changeでコールバックすれば選択した期間のデータを表示することも可能です。ぜひお試しあれ。(期間が長いとデータのロードに時間がかかるので注意です)

まとめ

というわけで今回はstreamlitの基本機能をまとめてみて、試しに株価ダッシュボードを作成してみました。

Pythonのシンプルなコードで簡単にwebブラウザアプリケーションを自作できるstreamlit。今後の機能追加にも期待です。

それでは〜。

参考ドキュメント

今回は基本的なよく使う機能を中心にまとめてみましたが、他にもメディア再生、プログレスバーの表示、エラー警告・例外処理など、streamlitでは色々な機能が提供されています。もっと深く使ってみたい方は公式のAPIリファレンスをご参考に。

Streamlit library | API reference

ads【オススメ】未経験からプログラマーへ転職できる【GEEK JOBキャンプ】
▼ Amazonオススメ商品
ディスプレイライト デスクライト BenQ ScreenBar モニター掛け式
スマートLEDフロアライト 間接照明 Alexa/Google Home対応

Author

Penta

都内で働くITエンジニアもどき。好きなものは音楽・健康・貯金・シンプルでミニマルな暮らし。AWSクラウドやデータサイエンスを勉強中。学んだことや体験談をのんびり書いてます。TypeScript / Next.js / React / Python / AWS / インデックス投資 / 高配当株投資 More profile

Location : Tokyo, JPN

Contact : Twitter@penguinchord

Recommended Posts

Copy Right / Penguin Chord, ペンギンコード (penguinchord.com) 2022 / Twitter@penguinchord