本記事はDeNA 23 新卒 Advent Calendar 2022 の19日目の記事です。
こんにちは。DeNA23卒内定者の juni です。
現在大学院修士2年で、情報系の研究室でアルゴリズムと最適化に関する研究を行っています。
今回は、Pythonのデータサイエンス用Webフレームワークの Streamlit について、簡単なアプリケーションを作成しつつ紹介します!
Streamlit とは
Streamlit は、機械学習やデータサイエンス向けのオープンソースWebフレームワークです。特徴として、
- Pythonで全てのコードを記述することができ、HTMLやCSS、JavaScript といったフロントエンドの知識が不要
- Pythonのライブラリとの相性が良く、PandasやMatplotlibなどを用いて表・グラフをそのまま表示することができる
- 公式でデプロイ用のクラウドサーバー(Streamlit Cloud)が用意されており、無料で簡単にデプロイできる
があります。同じPythonのフレームワークであるDjangoやFlaskに比べて、機能は限られている分、手軽に開発出来るところが強みです。
作ったもの
まずは簡単なアプリケーションを実装しようと思い、学食のメニューの組合せを自動で選ぶアプリを作成しました。(メニューは実データではなくサンプルです。)
Webアプリ
GitHubリポジトリ
導入手順
Webアプリ開発ではバージョンの干渉を防ぐため、 pipenv などの仮想環境を準備することをお勧めします。今回は Python3.11 で導入しましたが、バージョン3.7以降であれば問題なく動くと思います。
参考:Pipenvを使ったPython開発まとめ - Qiita
インストール
$ pip install streamlit
ちなみに、Streamlit上で描画できるライブラリ(NumpyやMatplotlib,Pandasなど)が導入されていない場合、同時にインストールしてくれます。
動作確認
$ streamlit hello
実装
学食のメニュー情報を記したcsvファイルを準備し、app.py
として以下のように実装しました。
Pythonコード
このプログラムでは、画面描画をview
関数、商品の選択処理をfoods_select
関数に分けています。foods_select
関数では、Pythonのrandomモジュールを用いて価格、カロリーの制限を満たす商品を選んで出力しています。
Streamlitはコーディング規約が明確に定められていないため、書き方が人によって自由な気がします。適宜分かりやすいように関数やクラス、モジュールに分割するのが良いです。
import streamlit as st
import pandas as pd
import random
MENU_PATH = './menu.csv'
menu = pd.read_csv(MENU_PATH, index_col=0)
def foods_select(max_price, max_calorie):
lottery_ids = list(menu.index)
result_ids = []
total = {'price':0, 'calorie':0, 'salt':0}
while(total['price'] < max_price and total['calorie'] < max_calorie \
and len(lottery_ids) != 0):
selected_id = random.choice(lottery_ids)
selected_food = menu.loc[selected_id]
if total['price'] + selected_food.price <= max_price \
and total['calorie'] + selected_food.calorie <= max_calorie:
result_ids.append(selected_id)
total['price'] += selected_food.price
total['calorie'] += selected_food.calorie
total['salt'] += selected_food.salt
lottery_ids.remove(selected_id)
return result_ids, total
def view():
st.title('学食メニュー組合せ機🍚')
# 結果表示用
c_top = st.container()
# 実行ボタン
c_button = st.empty()
st.subheader('設定')
price_input = st.number_input(
'予算上限を決めてください(円)',
300, 3000, 1000, 100,
)
# チェックボックスが空の場合はinfになる
calorie_input = float('inf')
if st.checkbox('カロリーを気にする方へ'):
calorie_input = st.number_input(
'カロリー上限を決めてください(kcal)',
400, 3000, 700, 100,
)
if c_button.button('メニューを決める'):
result_ids, total = foods_select(price_input, calorie_input)
c_top.write(menu.loc[result_ids].style.format({'salt':'{:.1f}'}))
c_top.info("合計 {}円 {}kcal 塩分 {}g".format(int(total['price']), int(total['calorie']), round(total['salt'],1)))
# 折りたたみ要素
with st.expander('メニューを表示'):
st.subheader('メニュー表')
st.write(menu.style.format({'salt':'{:.1f}'}))
view()
ローカルでの起動
$ streamlit run app.py
Streamlit Cloud へのデプロイ方法
デプロイ方法は非常に簡単です。
あらかじめ作成したアプリケーションをGitHubに上げておきます。
1. Streamlit Cloudにアカウントを登録する
下記のリンクから、GmailやGitHubアカウントを使って登録ができます。
2. ホーム画面からNew appボタンを選択する
選択後にGitHubのサインインを求められる場合があります。
3. デプロイのための設定を行う
リポジトリ、ブランチ、メインファイルの設定を行えば完了です。
Advansed settings では、Pythonのバージョン、環境変数を設定することができます。
(補足)Streamlit Cloud 無料版の制約について
無料版では、
- 1アプリケーションあたりメモリ1GB
- プライベートアプリは一つまで
- パブリックアプリは無制限
という仕様になっています。
※ プライベートアプリ:Streamlit Cloudにログインしており、管理者が指定したメールアドレスのアカウントのみ閲覧できる。
まとめ
Streamlitは、フロント実装とデプロイの負担をできる限り軽減したフレームワークで、手軽にアプリケーションを作成・デプロイすることができました。
Pythonのみで書けるため、Webアプリケーション開発の敷居が下がったように感じます。(もちろん、Streamlitでは実装できない要件も多いですが...)
コーディングがとても楽しかったので、個人開発でもっと使ってみようと思います。