Streamlit に入門してみた

# 1. はじめに
[第38回 JAWS-UG札幌 勉強会 〜実践！Amazon Q Developer〜](https://jawsug-sapporo.connpass.com/event/330317/) で Amazon Q Developer のハンズオンをしたので Amazon Q Developer について書こうと息巻いていたのですが、業務で「Streamlit できるよね？」と無茶振りがきたので急遽 Streamlit を触ってみる回にしたいと思います。
Streamlit というワード自体、聞いたことがなかった状態からのスタートです。

# 2. Streamlit とは
[Streamlit 公式ページ](https://streamlit.io/)によると、以下のように記されています：

> A faster way to build and share data apps
> Streamlit turns data scripts into shareable web apps in minutes.
> All in pure Python. No front‑end experience required.

ここにあるように、データスクリプトを数分で共有可能な Web アプリに変えることができるようです。
しかも、フロントエンドの経験は不要で、です。

# 3. 基本的な機能を使ってみる
## 3.1. Streamlit のインストール
まずは Streamlit をインストールしていきます。インストールは以下のコマンドで一発です。

```bash
$ pip install streamlit
```

## 3.2. はじめての Streamlit
Python コードを記載するファイルを作成していきます。今回は `app.py` という名前のファイルを作成し、以下の内容を記載します。

```python
import streamlit as st

st.write('Hello Streamlit World')
```

作成したコードを実行するのは、以下のコマンドを実行します。

```bash
$ streamlit run app.py
```

そうすると、Streamlit によってホストされた Web アプリケーションがブラウザ上に表示されるはずです。Python コードがそのまま Web アプリケーションになってしまうなんて凄すぎですね…！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333253/848c1d42-b4b5-b99c-45ef-c3a781dcbde6.png)

ターミナル上には Web アプリケーションを表示するための URL が記載されています。

```bash
  You can now view your Streamlit app in your browser.

  Local URL: http://localhost:8501
  Network URL: http://***.***.***.***:8501

  For better performance, install the Watchdog module:

  $ xcode-select --install
  $ pip install watchdog
```

## 3.3. 基本的な関数を使ってみる
Streamlit に様々な関数が用意されており、それらを活用することで簡単に Web アプリケーションを作成することができます。以下では、Streamlit にある関数をいくつか触っていきたいと思います。

### 3.3.1. テキストの表示
```python
import streamlit as st

st.title('タイトル')
st.header('ヘッダ')
st.subheader('サブヘッダ')
st.text('テキスト')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333253/d82b3e34-8114-20c9-ddc0-29a90b2f7e4e.png)

### 3.3.2. Markdown 形式でのテキストの表示
```python
import streamlit as st

st.markdown('# タイトル')

st.markdown('---')

st.markdown('## ヘッダ')
st.markdown('### サブヘッダ')

st.markdown('* item 1')
st.markdown('* item 2')
st.markdown('* item 3')
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333253/2fa6cdba-131a-90de-d5ef-090e6581a214.png)

### 3.3.3. LaTeX 形式での数式の表示
```python
import streamlit as st

st.title('LaTeX 形式')

st.header('オイラーの等式')
st.latex(r'''
e ^{i\pi}+1=0
''')

st.header('行列')
st.latex(r'''
 \begin{pmatrix}
 a & b \\
 c & d
 \end{pmatrix}
''')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333253/a2fb72a0-a203-6648-915c-a8f1ff827dfd.png)

### 3.3.4. カラム
```python
import streamlit as st

# 2 列のカラムを作成
col1, col2 = st.columns(2)

# col1
with col1:
    st.header("Column 1")
    st.write("This is column 1.")

# col2
with col2:
    st.header("Column 2")
    st.write("This is column 2.")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333253/0aa8488b-e098-4cd4-f0d9-381141a52f3b.png)

### 3.3.5. タブ
```python
import streamlit as st

st.title("タブも使える")

# タブの作成
tabs = st.tabs([":house:**ホーム**", ":man:**プロフィール**", ":gear:**設定**"])

# 各タブのコンテンツ
with tabs[0]:
    st.header("ホーム")
    st.write("ホームのコンテンツ")

with tabs[1]:
    st.header("プロフィール")
    st.write("プロフィールのコンテンツ")

with tabs[2]:
    st.header("設定")
    st.write("設定のコンテンツ")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333253/4a9bf283-8461-a4fa-9750-f652f60861c2.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333253/b23b0f31-0c08-b286-cc6d-d56bba9418a9.png)

### 3.3.6. サイドバー
```python
import streamlit as st
 
st.title("サイドバー")

# サイドバーにセレクトボックスを追加
choice = st.sidebar.selectbox(
     "Select an option",
     ("Option 1", "Option 2", "Option 3")
 )

# Mainコンテンツの表示を変える
if choice == "Option 1":
    st.write("You selected Option 1")
elif choice == "Option 2":
    st.write("You selected Option 2")
else:
    st.write("You selected Option 3")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333253/693ce63e-0106-9fbf-de93-91e0036b0712.png)

### 3.3.7. 入力
```python
import streamlit as st
import datetime

# テキストボックス
user_input1 = st.text_input("テキストを入力してください", "text")

# テキストエリア
user_input2 = st.text_area("テキストを入力してください", "text area")

# チェックボックスを作成
agree1 = st.checkbox("check box")

# チェックボックスの状態に基づいてメッセージを表示
if agree1:
    st.write("チェックボックスがオンになっています")
else:
    st.write("チェックボックスがオフになっています")

# トグルを作成
agree2 = st.toggle("toggle")

# トグルの状態に基づいてメッセージを表示
if agree2:
    st.write("トグルがオンになっています")
else:
    st.write("トグルがオフになっています")

# ラジオボタン
options = ["PP", "AP", "VC"]
captions = [
    "aaaaaa",
    "bbbbbb",
    "cccccc"
]

selected_option = st.radio(
    'ラジオボタン',
    options = options,
    index = 0,
    captions = captions
)

# セレクトボックス
prefectures  = ["Tokyo", "Okinawa", "Hokkaido"]

selected_prefectures = st.selectbox(
    'セレクトボックス',
    options=prefectures,
    index = None,
    placeholder = "選択してください"
)

# マルチセレクトボックス
multiselected_prefectures = st.multiselect(
    'マルチセレクトボックス',
    options=prefectures,
    placeholder = "選択してください"
)

# スライダー
sharpness = st.slider('スライダー', -100, 100, 0)

# 数値入力
input_num = st.number_input('数値入力', value=0)

# 日付選択
input_date = st.date_input('日付選択', value=datetime.date(2024, 12, 14))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333253/4b3cfd58-7722-ab4b-4e18-13b2709ed2bf.png)

### 3.3.8. DataFrame
```python
import streamlit as st
import pandas as pd

# ダミーデータの作成
df = pd.DataFrame({
    'name': ['Alice', 'Bob'],
    'age': [25, 30],
    'gender': ['female', 'male']
})

# DataFrameを表示
st.write(df)
# st.dataframe()でも表示可能
st.dataframe(df)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333253/34590fa1-edc3-b2ae-dff6-5525eea0a724.png)

### 3.3.9. データの可視化
#### 折れ線グラフ
```python
import streamlit as st
import pandas as pd
import numpy as np

st.title('折れ線グラフ')

# ダミーデータの作成
dates = pd.date_range(start='2024-01-01', periods=100)
values1 = np.random.randn(100).cumsum()
values2 = np.random.randn(100).cumsum()

# データフレームの作成
data = pd.DataFrame({
    'date': dates,
    'column 1': values1,
    'column 2': values2
})

# ラインチャートの表示
st.line_chart(data.set_index('date'))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333253/cc8324c4-f202-5a05-495b-9328be608f7d.png)

#### 棒グラフ
```python
import streamlit as st
import pandas as pd
import numpy as np

st.title('棒グラフ')

# ダミーデータの作成
dates = pd.date_range(start='2024-01-01', periods=100)
values1 = np.random.randn(100).cumsum()
values2 = np.random.randn(100).cumsum()

# データフレームの作成
data = pd.DataFrame({
    'date': dates,
    'column 1': values1,
    'column 2': values2
})

# バーチャートの表示
st.bar_chart(data.set_index('date'))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333253/34e1c0e5-8e03-b491-e67d-7db0001d456d.png)

#### 散布図
```python
import streamlit as st
import pandas as pd
import numpy as np

st.title('散布図')

# ダミーデータの作成
dates = pd.date_range(start='2024-01-01', periods=100)
values1 = np.random.randn(100).cumsum()
values2 = np.random.randn(100).cumsum()

# データフレームの作成
data = pd.DataFrame({
    'date': dates,
    'column 1': values1,
    'column 2': values2
})

# スキャッターチャートの表示
st.scatter_chart(data.set_index('date'))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333253/ec272b98-9d66-fc48-7067-287b1d92381e.png)

# 4. まとめ
本稿では Streamlit に軽く触れてみました。Python だけでここまでフロントエンドができてしまうのにいちいち感動しながら動かすことができました。簡単な Web アプリケーションでよければ本当に数分でできそうですね。

業務としては、LangChain もある程度触れるようになる必要があるので、次は LangChain にも入門したいと思います。

それでは、良いお年を。