Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Streamlit 総合解説 ~ PythonistaのためのWebアプリ開発 ~

Avatar for MIKIO KUBO MIKIO KUBO
May 17, 2025
530

Streamlit 総合解説 ~ PythonistaのためのWebアプリ開発 ~

Avatar for MIKIO KUBO

MIKIO KUBO

May 17, 2025
Tweet

Transcript

  1. 3. Streamlit 基本操作 インストール: pip install streamlit 基本的なアプリ ( app.py

    ): import streamlit as st st.title("My First Streamlit App") st.write("Hello, Streamlit!") 実行: streamlit run app.py 4
  2. Magic コマンド Streamlitでは、 st.write() を使わずに変数やMarkdown文字列を直接書くと表示 できます。 import streamlit as st

    import pandas as pd "# タイトル" # st.title("タイトル") と同様 df = pd.DataFrame({'col1':[1,2], 'col2':[3,4]}) df # st.write(df) と同様 6
  3. 4. 表示系ウィジェット: テキスト import streamlit as st st.title("タイトル") st.header("ヘッダー") st.subheader("サブヘッダー")

    st.write("通常のテキストや変数を表示") st.markdown("Markdownも使えます: **太字**, *イタリック*") st.caption("これはキャプション(注釈)です") st.code("print('Hello, World!')", language='python') st.latex(r''' e^{i\pi} + 1 = 0 ''') 7
  4. 表示系ウィジェット: データ # DataFrame df = pd.DataFrame(np.random.randn(10, 5), columns=('col %d'

    % i for i in range(5))) st.dataframe(df) # インタラクティブ st.table(df.head()) # 静的 # JSON st.json({'foo': 'bar', 'baz': 'qux'}) # Metric st.metric(label="気温", value="25 °C", delta="1.5 °C") 8
  5. 表示系ウィジェット: メディア # 画像 (ローカルファイル or URL) try: st.image("https://streamlit.io/images/brand/streamlit-logo-secondary-colormark-darktext.png", caption="Streamlit

    Logo", width=300) except: st.warning("画像の読み込みに失敗しました。") # 音声 (ローカルファイル or URL) # st.audio("audio.mp3") # 動画 (ローカルファイル or URL) # st.video("video.mp4") 注: 音声・動画ファイルは別途用意する必要があります。 9
  6. 5. 入力系ウィジェット: ボタン # 通常ボタン if st.button("クリックしてください"): st.write("ボタンがクリックされました!") # ダウンロードボタン

    data = "これはダウンロードされるテキストデータです。" st.download_button( label="テキストファイルをダウンロード", data=data, file_name="sample.txt", mime="text/plain" ) # リンクボタン st.link_button("Streamlit公式サイトへ", "https://streamlit.io") 10
  7. 入力系ウィジェット: 選択 ( 単一) # チェックボックス agree = st.checkbox("利用規約に同意します") if

    agree: st.write("同意ありがとうございます!") # ラジオボタン genre = st.radio( "好きな映画のジャンルは?", ('コメディ', 'ドラマ', 'ドキュメンタリー'), index=None # デフォルト未選択 ) if genre: st.write(f"{genre}を選びましたね。") 11
  8. 入力系ウィジェット: 選択 ( 複数) # セレクトボックス (ドロップダウン) option = st.selectbox(

    "連絡方法は?", ('メール', '電話', 'Slack'), placeholder="選択してください..." ) st.write(f"選択: {option}") # マルチセレクト options = st.multiselect( "好きな色を教えてください", ['緑', '黄', '赤', '青'], ['黄', '赤'] # デフォルト選択 ) st.write("選択:", options) 12
  9. 入力系ウィジェット: テキスト入力 # 1行テキスト入力 name = st.text_input("名前を入力してください", placeholder="山田 太郎") if

    name: st.write(f"こんにちは、{name}さん!") # パスワード入力 password = st.text_input("パスワード", type="password") # 複数行テキスト入力 feedback = st.text_area("フィードバックをお願いします", height=150) 13
  10. 入力系ウィジェット: 数値・日時入力 import datetime # 数値入力 age = st.number_input("年齢を入力してください", min_value=0,

    max_value=120, value=25, step=1) st.write(f"年齢: {age}歳") # 日付入力 d = st.date_input("誕生日を選択してください", datetime.date(2000, 1, 1)) st.write('誕生日:', d) # 時間入力 t = st.time_input('会議の時間を設定してください', datetime.time(9, 00)) st.write('会議時間:', t) 14
  11. 入力系ウィジェット: スライダー # 数値スライダー level = st.slider("レベルを選択", 0, 100, 50)

    st.write(f"選択したレベル: {level}") # 範囲スライダー price_range = st.slider( "価格帯を選択", min_value=0, max_value=10000, value=(1000, 5000), step=100 ) st.write("選択した価格帯:", price_range) # セレクトスライダー (離散値) color = st.select_slider( '好きな色を選択', options=['赤', 'オレンジ', '黄', '緑', '青', '紫'] ) t it ('好きな色 ' l ) 15
  12. 入力系ウィジェット: その他 import pandas as pd # カラーピッカー color =

    st.color_picker('テーマカラーを選択', '#00f900') st.write('選択した色:', color) # ファイルアップローダー uploaded_file = st.file_uploader("CSVファイルをアップロード", type="csv") if uploaded_file is not None: df = pd.read_csv(uploaded_file) st.write("アップロードされたデータ:") st.dataframe(df.head()) 16
  13. 6. レイアウト: サイドバー # サイドバーに要素を追加 add_selectbox = st.sidebar.selectbox( "連絡方法は?", ("メール",

    "自宅電話", "携帯電話") ) add_slider = st.sidebar.slider( "範囲を選択してください", 0.0, 100.0, (25.0, 75.0) ) st.write("メインコンテンツエリア") st.write(f"サイドバーの選択: {add_selectbox}") st.write(f"サイドバーのスライダー: {add_slider}") st.sidebar.* でサイドバー内にウィジェットを配置。 17
  14. レイアウト: カラム ( 横並び) import numpy as np st.header("カラムレイアウト") col1,

    col2, col3 = st.columns(3) # 3つの均等なカラム with col1: st.write("ここは最初のカラムです。") st.image("https://static.streamlit.io/examples/cat.jpg") with col2: st.write("ここは中央のカラムです。") st.line_chart(np.random.randn(10, 1)) with col3: st.write("ここは最後のカラムです。") t b tt ("カラム3のボタン") st.columns() でカラムを作成し、 with 構文で各カラムに要素を追加。 18
  15. レイアウト: タブ import numpy as np st.header("タブレイアウト") tab1, tab2, tab3

    = st.tabs([" チャート", " データ", " 説明"]) with tab1: st.header("チャートタブ") st.line_chart(np.random.randn(20, 3)) with tab2: st.header("データタブ") st.dataframe(np.random.randn(20, 3)) with tab3: st.header("説明タブ") i (" れはタブ機能 デ トレ シ す ") st.tabs() でタブを作成し、 with 構文で各タブに要素を追加。 19
  16. レイアウト: エキスパンダー ( 折りたたみ) import streamlit as st st.header("エキスパンダー") st.bar_chart({"data":[1,5,2,6,7,8,8})

    with st.expander("詳細を見る"): st.write(""" このチャートはランダムなデータを表示しています。 エキスパンダーを使うことで、詳細情報を隠しておき、 ユーザーが必要な時に展開できるようにします。 """) st.image("https://static.streamlit.io/examples/dice.jpg") st.expander() で折りたたみ可能なセクションを作成。 20
  17. レイアウト: 空の要素 ( st.empty ) import streamlit as st import

    time st.header("st.empty: 動的更新") placeholder = st.empty() # 空のプレースホルダーを作成 # プレースホルダーに要素を追加 placeholder.text("処理を開始します...") time.sleep(2) # プレースホルダーの内容を上書き placeholder.text("処理中です... 50%") time.sleep(2) # さらに上書き l h ld ("処理が完了しました!") st.empty() で作成したプレースホルダーの内容を後から書き換えられる。プログレ ス表示などに便利。 21
  18. レイアウト: コンテナ(複数を格納できる) import time st.header("コンテナ") st.write("1行目") st.write("---") container = st.container()

    st.write("---") st.write("2行目") time.sleep(5) container.write("3行目") container.write("4行目") st.container() で要素をグループ化。表示順序の制御などに使う。 22
  19. 7. グラフ・チャート: 基本チャート import streamlit as st import pandas as

    pd import numpy as np st.header("Streamlit組み込みチャート") chart_data = pd.DataFrame( np.random.randn(20, 3), columns=['a', 'b', 'c']) # ラインチャート st.subheader("ラインチャート") st.line_chart(chart_data) # エリアチャート st.subheader("エリアチャート") st.area_chart(chart_data) 23
  20. グラフ・チャート: Matplotlib import streamlit as st import matplotlib.pyplot as plt

    import numpy as np st.header("Matplotlib") arr = np.random.normal(1, 1, size=100) fig, ax = plt.subplots() ax.hist(arr, bins=20) ax.set_title("Matplotlib Histogram") st.pyplot(fig) st.pyplot() で Matplotlib の Figure オブジェクトを表示。 24
  21. グラフ・チャート: Plotly import streamlit as st import plotly.express as px

    import pandas as pd st.header("Plotly") df = px.data.iris() # Plotly組み込みデータセット fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species", title="Plotly Scatter Plot") st.plotly_chart(fig, use_container_width=True) st.plotly_chart() で Plotly の Figure オブジェクトを表示。インタラクティブな 操作が可能。 25
  22. グラフ・チャート: Altair import streamlit as st import altair as alt

    import pandas as pd import numpy as np st.header("Altair") chart_data = pd.DataFrame( np.random.randn(20, 3), columns=['a', 'b', 'c']) c = alt.Chart(chart_data).mark_circle().encode( x='a', y='b', size='c', color='c', tooltip=['a', 'b', 'c']) st.altair_chart(c, use_container_width=True) st.altair_chart() で Altair の Chart オブジェクトを表示。 26
  23. グラフ・チャート: 地図 (Pydeck) import streamlit as st import pandas as

    pd import numpy as np import pydeck as pdk st.header("地図 (Pydeck)") # 東京駅周辺のランダムな点を生成 chart_data = pd.DataFrame( np.random.randn(100, 2) /[100,100] + [35.68, 139.76], columns=['lat', 'lon']) st.pydeck_chart(pdk.Deck( map_style=None, # or 'mapbox://styles/mapbox/light-v9' など initial_view_state=pdk.ViewState( latitude=35.68, longitude=139.76, zoom=11, pitch=50, ), layers=[ pdk.Layer( 'HexagonLayer', data=chart_data, get_position='[lon, lat]', radius=100, st.pydeck_chart() で Pydeck を使った高度な地図可視化。 27
  24. なぜSession State が必要か? ( 復習) # counter_bad.py st.title('カウンター (問題あり)') count

    = 0 # リランのたびに0に初期化される increment = st.button('増加') if increment: count += 1 st.write('カウント = ', count) # クリックしても常に1になる ボタンを押すとリランが発生し、 count が毎回0に戻ってしまう。 29
  25. Session State の初期化 値を保持したい変数がSession State内に存在するか確認し、なければ初期値を設定 する。 if 'key' not in

    st.session_state: の形式が一般的。 # 'count' が session_state になければ 0 で初期化 if 'count' not in st.session_state: st.session_state['count'] = 0 # または st.session_state.count = 0 st.write("初期化後のSession State:", st.session_state) 30
  26. Session State の値の読み書き 辞書のようにキーを指定するか、属性アクセスで値を読み書きできる。 if 'my_value' not in st.session_state: st.session_state['my_value']

    = "Initial Value" # 値の読み取り current_value = st.session_state['my_value'] st.write(f"現在の値: {current_value}") # 値の書き込み (更新) if st.button("値を更新"): st.session_state.my_value = "Updated Value!" # または st.session_state['my_value'] = "Updated Value!" 31
  27. Session State を使ったカウンターアプリ ( 改善版) # counter_good.py st.title('カウンター (Session State使用)')

    # 'count' が session_state になければ 0 で初期化 if 'count' not in st.session_state: st.session_state.count = 0 increment = st.button('増加') if increment: st.session_state.count += 1 # Session Stateの値を更新 st.write('カウント = ', st.session_state.count) # Session Stateの値を表示 これでボタンをクリックするたびにカウントが増加する。 32
  28. Session State とウィジェットの状態連携 ウィジェットに key 引数を指定すると、そのウィジェットの状態が Session State に自動的に保存・同期される。 st.title("ウィジェットとSession

    Stateの連携") # スライダーに key を設定 temp_c = st.slider( "温度 (°C)", min_value=-50.0, max_value=50.0, value=25.0, step=0.1, key="celsius" # このキーで Session State に保存される ) # Session State を使ってスライダーの値を取得・表示 st.write(f"Session Stateから取得した温度: {st.session_state.celsius} °C") 33
  29. Session State とウィジェット連携の注意点 ウィジェットの状態は、Session State API を使って 直接設定(書き込み)すること はできない。 ウィジェットの状態を読み取ることは可能。

    # これはエラーになる例 # if 'my_button_state' not in st.session_state: # st.session_state.my_button_state = True # ボタンの状態は設定できない # st.button('エラーになるボタン', key='my_button_state') # -> StreamlitAPIException # 読み取りは可能 if st.button("クリックして状態確認", key="confirm_button"): st.write(f"ボタンの状態 (押されたか): {st.session_state.confirm_button}") 34
  30. Session State の応用例: ユーザー入力の保持 st.title("ユーザー入力の保持") # Session State の初期化 if

    'user_name' not in st.session_state: st.session_state.user_name = "" name = st.text_input("名前を入力してください", key="user_name_input") # Session State に入力値を保存 # この例では、次のリランで text_input が st.session_state.user_name を使う st.session_state.user_name = name if st.session_state.user_name: st.write(f"こんにちは、{st.session_state.user_name} さん!") else: st.write("まだ名前が入力されていません。") 後述のコールバックを使うと、入力と同時にSession Stateを更新できる。 35
  31. Session State の応用例: 簡易認証(1) # Session State の初期化 if 'logged_in'

    not in st.session_state: st.session_state.logged_in = False def login(): # 実際の認証処理 (ここでは簡略化) if st.session_state.username == "user" and st.session_state.password \n == "pass": st.session_state.logged_in = True else: st.error("ユーザー名またはパスワードが違います") def logout(): st.session_state.logged_in = False # 他のセッション情報もクリアすることが望ましい # t i t t "" など 36
  32. Session State の応用例: 簡易認証(2) # --- ログイン画面 --- if not

    st.session_state.logged_in: st.text_input("ユーザー名", key="username") st.text_input("パスワード", type="password", key="password") st.button("ログイン", on_click=login) # --- ログイン後画面 --- else: st.write(f"ようこそ、{st.session_state.username} さん!") st.button("ログアウト", on_click=logout) 37
  33. Session State と st.cache の違い Session State: 目的: ユーザーインタラクションの状態や、リラン間で 変更される可能性のある

    変数を保持。 スコープ: セッションごと(ユーザーごと、タブごと)。 例: カウンターの値、フォームの入力内容、ログイン状態。 st.cache_data / st.cache_resource : 目的: 時間のかかる計算結果や、リソース(モデル、DB接続など)をキャッシュ して パフォーマンスを向上。 スコープ: 全セッションで共有されることが多い(引数による)。 例: 大規模データの読み込み、機械学習モデルのロード、APIからのデータ取 得。 38
  34. Session State の中身を確認 Session State は辞書ライクなオブジェクトなので、そのまま表示できる。 if 'counter' not in

    st.session_state: st.session_state.counter = 0 if 'text' not in st.session_state: st.session_state.text = "Hello" st.session_state.counter += 1 st.text_input("テキスト", key="text") st.write("現在のSession State:") st.write(st.session_state) # そのまま表示 # またはマジックコマンドで: # st.session_state 39
  35. Session State のキーの削除 Pythonの辞書と同様に del を使って削除できる。 if 'temp_data' not in

    st.session_state: st.session_state.temp_data = "一時的なデータ" st.write("削除前のSession State:", st.session_state) if st.button("一時データを削除"): if 'temp_data' in st.session_state: del st.session_state['temp_data'] st.success("一時データを削除しました。") else: st.warning("一時データは既に存在しません。") st.write("削除後のSession State:", st.session_state) 40
  36. コールバック関数とSession State ( 詳細) # コールバック関数: テキスト入力が変更されたら呼ばれる def update_text(): st.session_state.text_value

    =st.session_state.my_text_input.upper() #text_value状態の初期化 if "text_value" not in st.session_state: st.session_state.text_value = "" # テキスト入力ウィジェットに key と on_change を設定 st.text_input( "テキストを入力 (入力後にEnterかフォーカスを外すとコールバック実行):", key="my_text_input", # Session Stateに値を保存するキー on_change=update_text # 値が変更されたときに呼び出す関数 ) st.write(f"Session State に保存されたテキスト: {st.session_state.text_value}") 42
  37. コールバック引数 ( args , kwargs ) コールバック関数に追加の引数を渡すことができる。 if 'count' not

    in st.session_state: st.session_state.count = 0 def increment_counter(increment_value): st.session_state.count += increment_value st.info(f"{increment_value} だけ増加しました!") def set_value(key, value): st.session_state[key] = value st.info(f"キー '{key}' に値 '{value}' を設定しました。") # args を使用 st.button("+1", on_click=increment_counter, args=(1,)) st.button("+5", on_click=increment_counter, args=(5,)) # kwargs を使用 st.button("カウンターを0にリセット", on_click=set_value, kwargs={'key': 'count', 'value': 0}) 43
  38. Session State のベストプラクティスと注意点 初期化: アプリの最初に、使用するキーが存在するか確認し、なければ初期化する ( if key not in

    st.session_state: )。 キー名の衝突: ウィジェットの key と手動で設定するSession Stateのキー名が衝突 しないように注意する。 複雑な状態: 状態が非常に複雑になる場合は、クラスやデータクラスを使って状態を 構造化することを検討する。 メモリ使用量: Session State に巨大なデータを保存するとメモリを消費するので注 意。大きなデータはキャッシュ ( st.cache_data ) を検討する。 スコープ: Session Stateはセッション(タブ)固有。異なるユーザーやタブ間で状態 は共有されない。 44
  39. st.cache_data : データ計算結果のキャッシュ(1) 主な用途: DataFrameの処理、Numpy配列の計算、APIからのデータ取得など、 シリ アライズ可能(pickle 化可能)なデータオブジェクトを返す関数の結果をキャッシュ する。 デコレータ

    @st.cache_data を関数に付与する。 @st.cache_data # データ処理関数にデコレータを付与 def fetch_and_clean_data(url): st.write(f"データを取得中: {url}") # このメッセージは初回のみ表示されるはず time.sleep(3) # 時間のかかる処理をシミュレート df = pd.DataFrame(np.random.randn(20, 3), columns=['A', 'B', 'C']) # (実際にはここで pd.read_csv(url) や前処理を行う) return df st.title("st.cache_data のデモ") data_url_1 = "http://example.com/data1.csv" data_url_2 = "http://example.com/data2.csv" 46
  40. st.cache_data : データ計算結果のキャッシュ(2) st.subheader("データセット1") if st.button("データ1をロード"): df1 = fetch_and_clean_data(data_url_1) #

    同じ引数ならキャッシュが返る st.dataframe(df1) st.subheader("データセット2") if st.button("データ2をロード"): df2 = fetch_and_clean_data(data_url_2) # 引数が違うので再計算される st.dataframe(df2) st.subheader("再度データセット1") if st.button("データ1を再度ロード"): df1_again = fetch_and_clean_data(data_url_1) # キャッシュが使われるはず st.dataframe(df1_again) st.success("キャッシュからロードされました! (取得中のメッセージは表示されない)") 47
  41. st.cache_resource : リソースのキャッシュ 主な用途: 機械学習モデル、データベース接続、TensorFlowセッションなど、 シリア ライズできない、またはグローバルに共有したいリソースをキャッシュする。 デコレータ @st.cache_resource を関数に付与する。

    @st.cache_resource # リソース読み込み関数にデコレータを付与 def load_heavy_model(model_path): st.write(f"モデルをロード中: {model_path}") # このメッセージは初回のみ表示されるはず time.sleep(5) # 重いモデルのロードをシミュレート # model = load_model(model_path) # 実際のモデルロード処理 model = f"LOADED::{model_path}" # ダミーのモデルオブジェクト return model st.title("st.cache_resource のデモ") model_path = "path/to/my/model.h5" st.subheader("機械学習モデル") if st.button("モデルをロード/使用"): model = load_heavy_model(model_path) # 同じ引数ならキャッシュが返る st.write(f"使用中のモデル: {model}") # st.write(model.summary()) # 実際のモデル操作など 48
  42. キャッシュの仕組み 1. キャッシュデコレータ ( @st.cache_data , @st.cache_resource ) が付いた関数が呼 び出される。

    2. Streamlitは以下の要素から キャッシュキーを生成する: 関数のバイトコード 関数が依存する他のコード(関数内でimportしているモジュールなど) 関数に渡された 入力引数の値 キャッシュデコレータの引数( ttl (time to live) など) 3. 生成されたキャッシュキーがキャッシュストレージ内に存在するか確認。 4. 存在する場合: 保存されている結果を返し、関数本体は実行しない。 5. 存在しない場合: 関数本体を実行し、その結果をキャッシュキーと共にキャッシュス トレージに保存してから結果を返す。 49
  43. キャッシュのクリア キャッシュされた結果を意図的に削除したい場合がある (例: 元データが更新され た)。 @st.cache_data def get_current_time_cached(): st.write("関数実行: 現在時刻を取得中...")

    time.sleep(1) return time.time() st.title("キャッシュのクリア") st.write(f"キャッシュされた時刻: {time.ctime(get_current_time_cached())}") if st.button("キャッシュをクリア (st.cache_data)"): st.cache_data.clear() # st.cache_data でキャッシュされた全関数をクリア st.success("st.cache_data のキャッシュをクリアしました!") st.rerun() # ページを再読み込みして効果を確認 st.cache_data.clear() : @st.cache_data でキャッシュされたものすべて。 50
  44. キャッシュのパラメータ(1) デコレータに引数を渡してキャッシュの挙動を制御できる。 # TTL (Time To Live): 60秒間だけキャッシュを有効にする @st.cache_data(ttl=60) def

    get_data_with_ttl(): st.write("TTL付き関数実行中...") time.sleep(1) return random.randint(1, 1000) # max_entries: 最新5件の結果のみキャッシュ @st.cache_data(max_entries=5) def get_data_with_max_entries(param): st.write(f"max_entries付き関数実行中 (param={param})...") time.sleep(1) return f"Data for {param} is {random.random()}" # show_spinner: キャッシュミス時に関数実行中にスピナーを表示 @st.cache_data(show_spinner="重いデータを計算中...") d f i t ti () 51
  45. キャッシュのパラメータ(2) st.title("キャッシュパラメータ") st.subheader("TTL (Time To Live)") st.write(f"データ (60秒有効): {get_data_with_ttl()}") st.subheader("Max

    Entries") entry_param = st.number_input("パラメータ (1-10)", 1, 10, 1) st.write(f"データ (最新5件): {get_data_with_max_entries(entry_param)}") st.subheader("Show Spinner") if st.button("重い計算を実行"): result = expensive_computation() st.write(f"結果: {result}") ttl : キャッシュの有効期限(秒数 or timedelta )。 max_entries : キャッシュする最大エントリ数。LRU方式で古いものから削除。 show_spinner : キャッシュ実行中に表示するメッセージ(文字列)または False 。 52
  46. st.cache_data vs st.cache_resource の使い分けまとめ 特徴 st.cache_data st.cache_resource 主な用 途 データ、計算結果

    (シリアライ ズ可能) リソース、共有オブジェクト (シリアライズ 不可) 返すオ ブジェ クト DataFrame, Numpy配列, dict, list, 文字列など MLモデル, DB接続, Tensorflow Sessionなど コピー の挙動 結果の コピーを返す (変更して もキャッシュに影響なし) オブジェクトへの 参照を返す (変更するとキ ャッシュも変更される可能性あり) 安全性 スレッドセーフ スレッドセーフではない (注意が必要) 共有 主に計算結果の再利用 アプリ全体でのリソース共有 例 データロード・前処理、API コール結果 load_model() , create_db_connection() 53
  47. 10. フォーム ( st.form ) 目的: 複数の入力ウィジェットの値を、ユーザーが「送信」ボタンを押すまで まとめ て扱いたい場合に使う。 背景:

    通常、Streamlitでは各ウィジェットを操作するたびにリランが発生する。フォ ームを使うと、フォーム内のウィジェット操作ではリランせず、送信ボタンが押され たときに初めてリランし、フォーム内の全ウィジェットの値にアクセスできる。 54
  48. フォームの基本的な使い方(1) # 'my_form' というキーでフォームを作成 with st.form(key='my_form'): st.write("以下の項目を入力してください。") name = st.text_input("名前")

    age = st.number_input("年齢", min_value=0, max_value=120, step=1) fav_color = st.selectbox("好きな色", ["赤", "青", "緑"]) feedback = st.text_area("ご意見・ご感想") # フォーム専用の送信ボタン submitted = st.form_submit_button("送信") 55
  49. フォームの基本的な使い方(2) # 送信ボタンが押された後の処理 if submitted: st.success("フォームが送信されました!") st.write("--- 入力内容 ---") st.write(f"名前:

    {name}") st.write(f"年齢: {age}") st.write(f"好きな色: {fav_color}") st.write(f"フィードバック: {feedback}") # ここで入力データを使った処理(DB保存、メール送信など)を行う else: st.info("フォームを入力して送信ボタンを押してください。") with st.form(key=...) ブロック内にウィジェットを配置する。 ブロックの最後に st.form_submit_button() を置く。 送信ボタン ( submitted ) が True になったときに、フォーム内のウィジェットの値 を使って処理を行う。 56
  50. フォーム利用時の注意点 key は必須: st.form() には一意の key 引数が必要。 st.form_submit_button : フォーム内には必ず1つの

    st.form_submit_button が必 要。複数置くことはできない。 フォームのネスト: フォームの中に別のフォームを作ることはできない。 Session State との連携: フォーム内のウィジェットに key を指定すれば、送信時に その値が Session State にも反映される。ただし、フォームが送信されるまでは Session State は更新されない。 条件分岐: フォームを if 文の中に入れることは推奨されない。常にレンダリングさ れる場所に置くのが基本。 58
  51. マルチページアプリの基本的な構造 1. メインのアプリファイル (例: main_app.py ) を作成する。 2. メインファイルと同じディレクトリに pages

    という名前の サブディレクトリを作成 する。 3. pages ディレクトリ内に、各ページに対応する .py ファイルを作成する (例: pages/01_Data_Upload.py , pages/02_Visualization.py )。 your_project/ ├── main_app.py # メインページ (最初に表示される) ├── pages/ # このディレクトリ名が重要 │ ├── 01_ _Data_Upload.py │ ├── 02_ _Visualization.py │ └── About.py └── requirements.txt main_app.py を実行 ( streamlit run main_app.py ) すると、サイドバーに自動的に ページナビゲーションが表示される[12]。 60
  52. ページの順序と表示名 ページの順序は、 pages ディレクトリ内のファイル名の 辞書順で決まる。 数字やアンダースコアで始まるプレフィックスを使うと順序を制御しやすい (例: 01_ , 02_

    )[12]。 プレフィックスを除いたファイル名(アンダースコアはスペースに置換)が、サイド バーでの表示名になる[12]。 01_Data_Upload.py → "Data Upload" About.py → "About" ファイル名に絵文字を入れると、それがアイコンとして表示される (例: )。 61
  53. 各ページのコード例 main_app.py ( ホームページ) import streamlit as st st.set_page_config(page_title="マルチページアプリ Demo",

    layout="wide") st.title("ようこそ!") st.sidebar.success("上のメニューからページを選択してください。") st.markdown( """ これはStreamlitのマルチページ機能のデモンストレーションです。 サイドバーから他のページに移動できます。 """ ) pages/01_ _Data_Upload.py ( データアップロードページ) import streamlit as st import pandas as pd 62
  54. st.set_page_config 各ページの最初に呼び出すことで、そのページのタブタイトル、アイコン、レイアウ トなどを設定できる[12]。 メインファイル ( main_app.py ) と各ページファイル ( pages/*.py

    ) の 両方で呼び出 すのが一般的。 よく使う引数: page_title : ブラウザタブに表示されるタイトル。 page_icon : タブアイコン (絵文字、URL、ローカルパス)。 layout : "centered" (デフォルト) or "wide" 。 initial_sidebar_state : "auto" , "expanded" , "collapsed" 。 63
  55. ページ間でのデータ共有 マルチページアプリの各ページは独立したスクリプトとして実行されるため、通常の 変数共有はできない。 Session State ( st.session_state ) を使うことで、ページ間でデータを共有できる [12]。

    前のページの例のように、あるページで処理した結果(例: アップロードされた DataFrame)を Session State に保存し、別のページでそれを読み出して使う。 64
  56. ページ遷移 ( st.page_link ) Streamlit 1.33 で導入された、プログラム的にページ遷移を行うための新しい API[13]。 ボタンのようなUIで他のページへのリンクを表示できる。 #

    基本的な使い方 (ファイルパスを指定) st.page_link("pages/01_ _Data_Upload.py", label="データアップロードページへ", icon=" ") # Aboutページへのリンク (pages ディレクトリ内) st.page_link("pages/About.py", label="Aboutページ") # ホームページ (メインアプリファイル) へのリンク st.page_link("main_app.py", label="ホームページに戻る", icon=" ") label : リンクの表示テキスト。 icon : 表示アイコン。 disabled : True にするとリンクが無効(クリック不可)になる。 65
  57. テーマのカスタマイズ ( config.toml ) (1) アプリの配色、フォントなどを変更できる。 方法1: 設定メニュー ( 一時的)

    アプリ右上の「 」メニュー → "Settings" → "Edit active theme"。 GUIで色などを変更でき、リアルタイムで反映される。 方法2: config.toml ( 永続的) アプリのルートディレクトリに .streamlit というフォルダを作成し、その中 に config.toml ファイルを作成する。 config.toml にテーマ設定を記述する。 67
  58. テーマのカスタマイズ ( config.toml ) (2) .streamlit/config.toml の例: [theme] primaryColor="#F63366" #

    アクセントカラー (ウィジェットなど) backgroundColor="#FFFFFF" # 全体の背景色 secondaryBackgroundColor="#F0F2F6" # サイドバーやエキスパンダーなどの背景色 textColor="#262730" # メインテキストの色 font="sans serif" # フォント (sans serif, serif, monospace) # サーバー設定などもここに記述可能 # [server] # port = 8501 # headless = true # ヘッドレスモード (ブラウザを自動で開かない) # [logger] # level = "info" 設定可能な項目は公式ドキュメント参照。 68
  59. デプロイオプション 作成したStreamlitアプリを他者がアクセスできるように公開する方法: Streamlit Community Cloud: (推奨、無料) Streamlit社が提供するホスティングサービス。 GitHubリポジトリから直接デプロイできる。 無料枠があり、公開・限定共有が可能。 Hugging

    Face Spaces: (無料オプションあり) 機械学習デモのホスティングに強い。Streamlitアプリも簡単にデプロイ可能。 AWS, GCP, Azure: (IaaS/PaaS) EC2, App Engine, App Service などで柔軟にデプロイ可能。インフラ管理が必 要。 社内サーバー: 企業のイントラネット内などで実行。 70
  60. Secrets Management ( 機密情報の管理)(1) APIキー、データベースパスワードなどの機密情報は、コードに直接書き込まず、安 全に管理する必要がある。 Streamlit Community Cloud: アプリの設定画面から

    Secrets を登録できる。 登録した Secrets は st.secrets 辞書ライクオブジェクト経由でアクセスでき る。 # .streamlit/secrets.toml (ローカル開発用) # API_KEY = "your_local_api_key" # DB_PASSWORD = "your_local_db_password" # アプリコード内 import streamlit as st api_key = st.secrets["API_KEY"] db_pw = st.secrets["database"]["password"] # ネストも可能 72
  61. Secrets Management ( 機密情報の管理)(2) その他の環境: 環境変数 ( os.environ.get("API_KEY") ) を使うのが一般的。

    .env ファイルと python-dotenv ライブラリを使う。 各クラウドプロバイダーのシークレット管理サービス (AWS Secrets Manager, Google Secret Manager など) を利用する。 73
  62. Streamlit Community Cloud へのデプロイ手順概略(1) 1. GitHub リポジトリ準備: Streamlitアプリのコード ( app.py

    または main_app.py ) requirements.txt ファイル 必要なら .streamlit/config.toml や pages/ ディレクトリ これらをGitHubの 公開または 非公開リポジトリに push する。 2. Streamlit Community Cloud にサインアップ/ ログイン: share.streamlit.io にアクセスし、GitHubアカウントで連携。 3. "New app" ボタンをクリック: デプロイしたいGitHubリポジトリを選択。 ブランチ名 (通常 main または master ) を指定。 メインのPythonファイル名を指定。 (オプション) 詳細設定 (Pythonバージョンなど)。 74
  63. Streamlit Community Cloud へのデプロイ手順概略(2) 4. Secrets を設定 ( 必要な場合): デプロイ前に、"Advanced

    settings..." から Secrets を入力する。 5. "Deploy!" ボタンをクリック: Streamlitが必要なパッケージをインストールし、アプリをビルド・起動する。 完了すると、固有のURL ( your-app-name.streamlit.app ) が発行され、アプリ にアクセスできる。 75
  64. 学習リソース 公式ドキュメント: docs.streamlit.io - 最も正確で網羅的な情報源。APIリファレン ス、チュートリアル、コンセプト解説が充実。 チートシート: docs.streamlit.io/library/cheatsheet - よく使うコマンドの早見表。

    ギャラリー: streamlit.io/gallery - 様々なStreamlitアプリの例とソースコード。イン スピレーションを得られる。 コミュニティフォーラム: discuss.streamlit.io - 質問したり、他のユーザーと交流し たりできる場。 77
  65. さらに学ぶべきこと カスタムコンポーネント開発: 独自のUI/UXを実現。 パフォーマンスチューニング: 大規模データや複雑な処理への対応。キャッシュの高 度な利用。 テスト: Streamlitアプリのテスト手法。 FastAPI との連携:

    Streamlitをフロントエンド、FastAPIをバックエンドAPIとして組 み合わせる構成。より複雑なバックエンドロジックやデータベース操作に対応。 認証・認可: よりセキュアなアプリ構築 (例: streamlit-authenticator コンポーネ ント)。 Streamlit for Teams / Snowflake SiS: エンタープライズ向けの機能とデプロイ。 78