30 Days of Streamlitにチャレンジしてみた (Day 11～Day 20)

## Streamlitとは

StreamlitはPython向けのWebアプリケーションフレームワークです。  

https://streamlit.io/

Streamlitを使うとフロントエンドの知識ゼロでもデータを可視化するためのWebアプリケーションを簡単に作れます。以下のような機能が特徴。  
- 変数を地の文に書くだけで、GUIに出力される(**マジックコマンド**)
- `st.radio`や`st.text_input`のようなWidget APIを呼び出すだけで、GUIコンポーネントが生成される

[30 Days of Streamlit](https://blog.streamlit.io/30-days-of-streamlit/)はStreamlitのチュートリアルコンテンツ。SNSに進捗を共有しながらちょっとづつStreamlitを学習できます。  
`#30DaysOfStreamlit`で検索すると先人たちのチャレンジの記録がたくさん！  
やっていきましょう。  

## Day 10まで

Day 10までの日記は[こちら](https://qiita.com/ak-sakatoku/items/f0c56d302cf14922b4c7)。

## Day 11

Day 11は```multiselect```…って何？  
動かしてみたらこういうの！よく見るやつ！  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917580/4614602e-a9a3-d7ce-6002-33bf57c0ea41.png)

以下のような感じで選択肢とデフォルトで選んでおくものを指定すればOK！  
オシャレだから何かに使いたい。  

```
options = st.multiselect(
     'What are your favorite colors',
     ['Green', 'Yellow', 'Red', 'Blue'],
     ['Yellow', 'Red'])
```

## Day 12

Day 12はチェックボックスが登場。  

```python
icecream = st.checkbox('Ice cream')
```

```st.checkbox```はチェックボックスを作って、そのチェックボックスがチェックされているかどうかをTrue/Falseで返してくれます。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917580/56e0cc93-fa51-8b4f-2069-74b755f7f542.png)

注意事項：  
2023/7/24時点で日本語版の30 Days of Streamlitは絵文字が```??```に文字化けしています。

## Day 13

Day 13はGitpodを使ってみようという内容でした。  
とりあえずGitpodを自分のリポジトリと連携してみる。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917580/ced35514-70dc-4c83-9df7-744f7622bf55.png)

ちょこちょこ初期設定をしてがえるとブラウザ上でVisualStudio Codeが起動！  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917580/31d98881-5382-a70b-f17d-fdb31b9d1577.png)

```streamlit run```も実行可能。  
ただし、```streamlit run```したときにGitpodのコンソールに表示されるURL(例：```Network URL: http://10.0.5.2:8502```)を開いても接続できない。  
インターネットに公開されていて接続できるURLはGitpodの管理コマンド```gp ports list```で調べられるみたい。  
試しに実行してみると

```sh
| PORT |     STATUS     | PROTOCOL |                                 URL                                 | NAME & DESCRIPTION |
|------|----------------|----------|---------------------------------------------------------------------|--------------------|
| 8501 | open (private) | http     | https://8501-sakatoku-streamlithello-utvq6be78r8.ws-us102.gitpod.io |                    |
| 8502 | not served     | http     | https://8502-sakatoku-streamlithello-utvq6be78r8.ws-us102.gitpod.io |                    |
```

STATUSがopenになっているURLをブラウザで開いてみると、無事に接続できました！  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917580/a3747136-7236-432f-c0b3-c79bd8f92c47.png)

## Day 14

Day 14はStreamlitコンポーネントを使ってみようという内容でした。  
StreamlitコンポーネントはStreamlitを機能拡張するためのユーザライブラリだそうです。  
Day 14で紹介されているのは、Pandas DataFrameに格納されているデータを解析してサマリーを作成してくれるライブラリ。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917580/c46db78d-d962-cdf3-45eb-a26422825ea1.png)

これを動かすためにはあらかじめ```pip install streamlit-pandas-profiling```しておく必要がありました。  
Streamlit Cloudでは```pip install```ができないけど、代わりにプロジェクトのトップディレクトリに```requirements.txt```に配置すればOK。  

```txt:requirements.txt
# Requirements without Version Specify
streamlit-pandas-profiling
```

Streamlitコンポーネント、他にも色々ありそう。  
例えば```streamlit-folium```は地図を表示するライブラリ```Folium```をStreamlitコンポーネントにしたものらしいです。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917580/3bf397fe-6347-5a0e-e1a0-1ad97daa6ec9.png)

何かと使えそう！

## Day 15

Day 15はLaTeXのレンダリング。LaTeX！？  

```py:streamlit_app.py
st.latex(r'''
     a + ar + a r^2 + a r^3 + \cdots + a r^{n-1} =
     \sum_{k=0}^{n-1} ar^k =
     a \left(\frac{1-r^{n}}{1-r}\right)
     ''')
```

昔はツールのインストールが大変だったLaTeXがあっさり…  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917580/8b0afdca-b1c2-0f58-7c31-8c6d541f0809.png)

積分記号のカーブが綺麗。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917580/ee04da7d-74e7-b015-2e70-4f4a228cc47c.png)

## Day 16

Day 16はカスタムテーマ！フォントや背景の色を変更できるようになりました。  
設定できる項目は[Streamlitのドキュメント](https://docs.streamlit.io/library/advanced-features/theming)に記載がありました。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917580/610590d2-1447-5b77-4886-2e9b7086eac3.png)

カスタムテーマを適用するときに気を付けることがいくつかあります。  
- ファイルを置くディレクトリは```.streamlit```。Linuxだとおなじみの**ドットで始まるディレクトリ**！
- ```streamlit run```を再起動しないと適用されない
- ブラウザのキャッシュが効いていて適用されないことがある。ブラウザのシークレットモードで開き直すととりあえず解決できる

チュートリアルには書かれていませんが、カスタムテーマを解除するときは、
右上のハンバーガーメニューの```Settings```から```Choose app theme, colors and fonts```を選択すればいいそうです！  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917580/2b22bc85-b62b-fbcc-ea9e-5bb465fd3e45.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917580/61cfeac0-9d02-20d6-8ea1-b4ebb11046dc.png)

チュートリアルのカスタムテーマはちょっと見づらいよね。  

## Day 17

Day 17は```st.secrets```。パスワードやAPIアクセスキーを保存するための機能だそうです。  
パスワードやAPIアクセスキーをソースコードにハードコーディングするのはダメだよね！  

とりあえずサンプルコードをコピペしてみると、

```
FileNotFoundError: No secrets files found. Valid paths for a secrets.toml file are:
C:\Users\user\.streamlit\secrets.toml,
C:\Users\user\Documents\project\streamlit\.streamlit\secrets.toml
```

```.streamlit\secrets.toml```を読み込もうとしているみたいなので、ファイルを作ってみました。  

```toml:secrets.toml
sample_username = "Jane"
sample_password = "12345qwerty"
```

プログラムからはディクショナリとして扱えるようです。  

```py:streamlit_app.py
st.write('sample_usernameの値は: ' + st.secrets['sample_username'])
st.write('sample_passwordの値は: ' + st.secrets['sample_password'])
```

無事に読み込めました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917580/0b15d2e2-414b-777f-25b6-266e8277bc4b.png)

## Day 18

Day 18はファイルアップローダー！  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917580/cd33d59f-fee9-df40-9adb-f7cad720c772.png)

ファイルがアップロードされると```UploadedFile```という```BytesIO```の派生クラスが返ってきます。これを```pd.read_csv```のようなファイル読み込みできるAPIに渡してあげればOK！  

```py:streamlit_app.py
uploaded_file = st.file_uploader("Choose a file")

if uploaded_file is not None:
  df = pd.read_csv(uploaded_file)
```

試しにCSVをアップロードしてみると、これは便利！  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917580/c26a99a7-459e-625f-2fe9-e5c141a5ed19.png)

ただし、2023年8月現在、Streamlit in Snowflakeではこの```st.file_uploader```は未対応だそうです。残念…！

## Day 19

Day 19は画面のレイアウトをしてみようという内容でした。  
Streamlitで細かく画面を作り込むのはバッドプラクティス…という話も聞きますが、やっぱり簡単なレイアウトくらいはしたいですよね。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917580/8d391917-cf17-b341-9578-1d89586f81de.png)

サンプルコードでは、サイドバーに入力を、コンテンツエリアに出力をまとめています。コンテンツエリアの出力は3列表示。  
さらに、Aboutは折り畳み(expander)で表示しています。  

サイドバーは```st.sidebar```を使うようです。

```py:streamlit_app.py
st.sidebar.header('Input')
user_name = st.sidebar.text_input('What is your name?')
```

```st.columns```を使うことでN列表示にできるようです。  
```st.columns```で返ってくるオブジェクトはそれぞれの列を示しているとのことで、with句にこのオブジェクトを指定してからこれまで学習してきた関数を呼び出すことでそれぞれの列に要素を追加できます。  
このオブジェクトは```st.container```というクラスで、このクラスに定義されている関数を直接呼びだしてもいいみたい。  
参考：[st.container](https://docs.streamlit.io/library/api-reference/layout/st.container)

```py:streamlit_app.py
col1, col2, col3 = st.columns(3)

with col1:
  if user_name != '':
    st.write(f'👋 Hello {user_name}!')
  else:
    st.write('👈  Please enter your **name**!')
```

折り畳み(expander)は```st.expander```を使うようです。シンプルで使いやすい！  

```py:streamlit_app.py
with st.expander('About this app'):
  st.write('This app shows the various ways on how you can layout your Streamlit app.')
  st.image('https://streamlit.io/images/brand/streamlit-logo-secondary-colormark-darktext.png', width=250)
```

## Day 20

Day 20はFrancesco CiullaさんのTwitter Space(今はX Spaceと呼ぶんでしょうか)を聞こう話そう！ということですが、残念ながらライブ配信が終わっています。悲しい。  
アーカイブ動画を探してみたのですが見つかりませんでした。  

どういう内容を話していたのかは今では分かりませんが、代わりに公式の動画を見てみようということで、Snowflake Developersにアップロードされている以下の動画を見てみました。

https://www.youtube.com/watch?v=482o28a8Fgc

## Day 21以降

Day 21以降は[こちら](https://qiita.com/ak-sakatoku/items/4b5e8bffab3cc5199d02)