basic1

Streamlit入門 – 1)Streamlitの基本

Streamlit入門の初回です。Streamlitはデータサイエンス分野で人気のあるWebフレームワークです。

  • expressやdjango, flaskなどを使ってサーバを自分で構築するのは面倒
  • Jupyter Notebookのまま公開するのは気が引ける
  • データの集計や加工に注力したい、公開は最小限の手間で済ませたい
  • チャットのGUIを簡単に作りたい

そんなときに最適な選択肢です。大量のデータを分析する場合、その結果を分かり易く提示するために、いわゆるダッシュボードというWebサイトが利用されますが、そのようなサイトを気軽に構築するためのフレームワークです。

本記事はFuture Coders独自教材からの抜粋です

試してみる

https://streamlit.io/

まず試してみましょう。以下の内容をコマンドラインから入力してください。

pip install streamlit
streamlit hello
basic1
Streamlit入門 - 1)Streamlitの基本 18

いくつかデモが用意されています。いろいろと操作して変化する様子をみてください。
streamlitコマンドを実行すると、ポート番号8501でWebサーバが起動します。ブラウザを終了してもサーバは停止しません。サーバーを終了する場合は、Ctrl+Cキーを押下してください。

動かしてみる

文字の描画

以下のコードを入力して、streamlit_app1.pyというファイルに保存します。

import streamlit as st
st.write("Hello World!")

コマンドライン(ターミナル)から以下のように入力して実行します。

streamlit run streamlit_app1.py

ブラウザが起動して以下の画面が表示されます。

basic2
Streamlit入門 - 1)Streamlitの基本 19

ブラウザやサーバはそのままの状態で、エディタでファイルを更新してください。例えば、Hello Streamlit!と書き換えてみましょう。サーバはファイルの更新を検出します。ブラウザを再読み込みすれば、新しい文字列が表示されます。

ボタンの描画

以下のコードを実行してください。

import streamlit as st

if st.button('Click Me'):
     st.write('こんにちは')

ボタンが描画されて、クリックすると”こんにちは”と表示されます。2回クリックしても表示は変わりません。

basic3
Streamlit入門 - 1)Streamlitの基本 20
basic4
Streamlit入門 - 1)Streamlitの基本 21

別の例をみてみましょう。

import streamlit as st

if st.button('Circle'):
     st.write('まる')
elif st.button('Rect'):
     st.write('四角')
else:
     st.write('それ以外')

最初に”それ以外”と表示されています。

basic5
Streamlit入門 - 1)Streamlitの基本 22

“Circle”ボタンをおすと”まる”と、”Rect”ボタンをおすと”四角”と表示されます。最初の状態に戻すには再読み込みを行います。

st.button(…)はボタンが押されたときにTrueを返します。その条件が成立したときにst.writeで書いた内容が画面に表示されます。
ボタンを押していないとst.buttonの条件は成立しないので、最初に実行したときには、elseにあったst.writeが実行されていました。

ボタンをクリックすると、ページ全体が最初から実行され、その状態に応じた処理が行われる、そのように考えるとよいでしょう。
ボタンを押すたびに実行されるという挙動は、「プログラムは上から順番に実行されてゆく」という考え方に慣れている人にとっては違和感を覚えるかもしれません。

Streamlitでいくつかコンテンツを作ってみると、この挙動にも慣れてくると思います。いろいろ手を動かしながら読み進めてください。

VSCodeでのデバッグ方法

このStreamlitの挙動はVSCodeのデバッガを使うと理解しやすくなるかもしれません。
あるフォルダを用意して、そこに上記のファイル(streamlit_app1.pyなど)をおいてください。デバッガのメニューから”create a launch.json file”というリンクをクリックしてください。この手順はフォルダの直下に.vscodeというフォルダを作成し、その下にlaunch.jsonというファイルを作成します。このファイルはVSCodeのカスタマイズを行うときに使用されます。手動で作成しても構いません。

basic6
Streamlit入門 - 1)Streamlitの基本 23

テンプレートを選択するよう促されるのでPython・Python Fileを選びます。

basic7
Streamlit入門 - 1)Streamlitの基本 24

launch.jsonの中身を以下のように修正してください。

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "debug",
            "type": "python",
            "request": "launch",
            "module": "streamlit", 
            "console": "integratedTerminal",
            "env": {
                "PYTHONPATH": "${workspaceFolder}",
            },
            "args": [
                "run",
                "${file}",
                "--server.port",
                "5678"
            ]
        }
    ]
}
basic8
Streamlit入門 - 1)Streamlitの基本 25

あとは、Explorer画面からデバッグ対象となるファイルを選択して、通常と同じようにデバッグ実行してください。以下はstreamlit_app2.pyをデバッグ実行している様子です。3行目と4行目にブレークポイントを設定しています。

デバッグ実行を開始すると3行目でストップします。継続実行するとページが表示されます。この時”Click Me”ボタンは押されていないので4行目ではストップしません。

basic9
Streamlit入門 - 1)Streamlitの基本 26

ページ表示後に”Click Me”ボタンを押下してください。再び3行目でプログラムが停止します。ステップ実行すると4行目に移動します。これはボタンを押下したたためst.button()がTrueになったことを意味しています。

つまり、ボタンが押されると、最初からプログラムが実行され、クリックされたボタンのst.buttonがTrueになっていることが確認できます。

以下は選んだボタンの種類を表示するサンプルです。

import streamlit as st

b0 = st.button('グー')
b1 = st.button('チョキ')
b2 = st.button('パー')

if b0:
    st.write("あなたはグーを選びました")
elif b1:
    st.write("あなたはチョキを選びました")
elif b2:
    st.write("あなたはパーを選びました")
else:
    st.write("ボタンをおしてください")

演習

ex-basic1.py

“おみくじ”というボタンを押すと、”大吉”,”中吉”,”小吉”,”凶”のどれかがランダムに表示されるページを作成してください。
配列からランダムに要素を抽出するには、randomモジュールのchoice関数が便利です。

basic
Streamlit入門 - 1)Streamlitの基本 27

ex-basic2.py

“松”,”竹”,”梅”と3つのボタンを表示します。最初は”コースを選んでください”と表示し、それぞれのボタンがおされたら2500円、2000円、1500円と値段を表示するサンプルを作成してください。

basic
Streamlit入門 - 1)Streamlitの基本 28

解答例

ex-basic1.py

import streamlit as st
from random import choice

if st.button("おみくじ"):
    r = choice(["大吉","中吉","小吉","凶"])
    st.write(r)

ex-basic2.py

import streamlit as st
from random import choice

b0 = st.button("松")
b1 = st.button("竹")
b2 = st.button("梅")

if b0:
    st.write("2500円です")
elif b1:
    st.write("2000円です")
elif b2:
    st.write("1500円です")
else:
    st.write("コースを選んでください")

いろいろな描画

st.writeで文字を描画することができました。

ここでは他の描画方法について説明します。

  • st.header = ヘッダ
  • st.subheader = サブヘッダ
  • st.caption = キャプション
  • st.text = テキスト
  • st.markdown = マークダウン
  • st.code = コード
  • st.image = 画像
  • st.write(引数) 引数に直接データを渡すことも可能です。
  • マークダウン形式
  • 数値
  • DataFrame = Pandasのデータフレーム

以下は文字やコードを描画するサンプルです。

import streamlit as st

st.title("This is title")
st.header("This is header")
st.subheader("This is subheader")
st.caption("This is caption")
st.text("This is text")
md = """
# markdown header1
## markdown header2
- item1
- item2
here is the *text* pargraph
"""
st.markdown(md)

code = """
import random
r = random.randint(1, 3)
print(r)
"""
st.code(code)

実行結果は以下のようになりました。

basic10
Streamlit入門 - 1)Streamlitの基本 29

以下はデータフレームとグラフを描画する例です。

import streamlit as st
import pandas as pd
import numpy as np
import altair as alt

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

df2 = pd.DataFrame(np.random.randn(200, 3),
     columns=['a', 'b', 'c'])

c = alt.Chart(df2).mark_circle().encode(
     x='a', y='b', size='c', color='c', tooltip=['a', 'b', 'c'])
st.write(c)
basic11
Streamlit入門 - 1)Streamlitの基本 30

詳しくは以下のURLを参照してください。
https://docs.streamlit.io/library/api-reference/text

HTMLの直接描画

Streamlitではunsafe_allow_html引数にTrueを指定することで、HTMLを直接埋め込むことも可能です。style要素によるスタイルも指定できます。

import streamlit as st

html = """
<style>
ul {color:red}
</style>
<h1 style="color:blue;">Hello World</h1>
<h3 style="color:green;">Streamlit</h3>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
"""

st.markdown(html,unsafe_allow_html=True)
basic12
Streamlit入門 - 1)Streamlitの基本 31

演習

ex-basic3.py

料理のレシピサイトを作成してください。

basic
Streamlit入門 - 1)Streamlitの基本 32

ex-basic4.py

以下のコードを参考にして、Seabornのデータセットからpenguinを読み込み、データフレームとコードを描画してください。

import seaborn as sns
df = sns.load_dataset("penguins")
basic
Streamlit入門 - 1)Streamlitの基本 33

解答例

ex-basic3.py

import streamlit as st

st.header("今日の料理")
st.subheader("カレーライス")
st.image("images/curry.jpg")
st.markdown("""
### 材料
- 肉:300g
- ジャガイモ:中2個
- 人参:小1本

### 作り方
1. 材料を切ります。
2. 肉を炒めます。
3. 煮込んでルーを入れます。
""")

ex-basic4.py

import streamlit as st
import pandas as pd
import seaborn as sns
df = sns.load_dataset("penguins")
st.header("Penguins")
st.write(df)

st.code("""
import streamlit as st
import pandas as pd
import seaborn as sns
df = sns.load_dataset("penguins")
st.header("Penguins")
st.write(df)
""")