見出し画像

1時間チャレンジ:Google ColabとStreamlitで簡単アプリ作成

はじめに


こんにちわ。マインディアの難波です。普段はデータ分析をしています。Tableauとか使って可視化することが多く、アプリ作るとかはできません。
ただ今回調べてみると、Tableauみたいなものを簡単につくれるみたいなのでそれをやってみようと思います。アプリの作成の体験ということで工数管理アプリのTogglのデータを使って分析アプリ作ってみようと思います。

余談

何度も挫折してきたプログラミングの独学ですが、昨今ブームの生成AIのおかげで、今まで以上に勉強しやすい環境が整ってきたなと思います。
Chat GPTにうまく質問しながら、勉強することができるようになったことで
心理的に勉強のハードルがめっちゃ下がりました。
(GPTの回答が正しいかは別にして、観点が見えるだけでもモチベーションへの影響大。)

記事の対象者

今回は、私と同じく、以下のような人向けに書いてみました。

・エンジニアではないがとりあえず作って、公開してみたい人
・プログラミング勉強したいが、何から始めればいいかわからない初心者

上記のような人はとりあえずミニマムで作ってみて、WEBアプリとしてアクセスできるようにするところまでやってみましょう。

この記事で理解を目指すもの

以下の観点がなんとなく理解できる状態を目指します。

  • 自分で決めたテーマのアプリを簡単に作成する方法もある

  • ユーザーの操作や、インプットを反映してアプリを動かす

  • 簡易のサーバーを立ててみて、アプリにアクセスする

今回作ってみるもの

作業時間振り返りのための工数分析ツール

Toggl TrackのAPIを使ってデータ分析ができるアプリを今回作ってみようと思います。工数を改めてきちんと確認してみて、自分の働き方の振り返りに活用を目指して。

準備物と全体像

今回は、以下の4つのツールを活用して、最速でアプリを作成してみたいと思います。
GPTの解説によると、、、大体はあってそう。

・Toggl Track

時間追跡およびプロジェクト管理ツールです。個人やチームがタスクやプロジェクトにかかる時間を追跡し、分析するのに役立ちます。ワンクリックでタイマーを開始・停止できるシンプルなインターフェイスが特徴で、デスクトップアプリ、モバイルアプリ、ウェブアプリで利用可能です。

https://toggl.com/track/

・Google colaboratory

Googleが提供するクラウド上で動作する無料のJupyterノートブック環境です。ブラウザからアクセスするだけで、Pythonプログラミングが可能で、専門的な設定なしに機械学習やデータ分析を実行できます。GPUやTPUなどの高速な計算リソースも無料で利用できるため、学術研究や個人プロジェクトにも手軽に利用できます。

https://colab.research.google.com/

・Streamlit

データサイエンティストやエンジニアがPythonで手軽にウェブアプリケーションを構築できるオープンソースのライブラリです。コーディングの専門知識が少なくても、短いコードでインタラクティブなダッシュボードやデータ可視化ツールを作成できる。

https://streamlit.io/

・Ngrok

ローカルネットワーク上で動作しているサーバーを、一時的に公開インターネット上に公開するためのツールです。開発中のウェブアプリケーションやAPIなどを外部からアクセス可能にするために使用できる

https://ngrok.com/

環境について

Python 3.10.12
streamlit 1.20.0
pyngrok 4.1.1

Google colabを開いて、準備します。
上部に表示されたタブ内の「ファイル」>「ノートブックを新規作成」で
アプリのコードを書き込むためのノートブックを新規で作成します。

https://colab.research.google.com/


事前準備として、以下2点をしておいてください。
各ライブラリ(Stremlit ,Ngork, Pandas , Numpy)など必要だが導入できていないものはインストールしておく。私の場合は、以下3点。


!pip install streamlit==1.20.0 --quiet
!pip install pyngrok==4.1.1 --quiet
!pip install japanize_matplotlib

Ngrokでのアカウント作成とトークンの取得

以下のページでアカウント作成

左のメニュー内の以下のページより、トークンの取得

トークンの取得ページ

以下の手順で作成していきます。

  1. TogglのデータにAPI経由でアクセス

  2. 簡単に分析したい内容を作成(データを可視化しアプリで表示する内容を準備)

  3. Streamlitに記述する(アプリ化)

  4. Ngrokでgoogle colabをサーバー化して、アプリを擬似デプロイ

実際に作ってみる

1.TogglのデータにAPI経由でアクセス

最初にこのあと使う全てのpythonライブラリをインストールしてしまいます。

#API経由でアクセスする際に通信するためのライブラリ
import requests
#API経由でログインする際のID等ASCIIに変換するためのライブラリ
from base64 import b64encode
#API経由で取得したデータをJSONとして扱う
import json
#アプリ作成のためのStremlitのインポート
import streamlit as st
#データを計算・可視化するためのライブラリ
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#matplotlibを日本語対応させるためのライブラリ
import japanize_matplotlib

TogglのデータにアクセスするAPIは以下の1行で完結です。

data = requests.get('https://api.track.toggl.com/api/v9/me/time_entries', headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' %  b64encode(b"YOUR ID:YOUR PASS").decode("ascii")})

YOUR ID:YOUR PASSの部分に、TogglのログインIDとパスを入力するだけで
データにはアクセスできます。

簡単にデータの内容を表示してみます。
dataの変数に格納したTogglのデータをjsonとして受け取り、それをfor_dataframeに格納して、最終的にpandasの標準化機能を用いて
dataframeを再格納して表示します。
(正直なぜjsonで扱う必要あるのかわかっていない、、)

for_dataframe = data.json()
df = pd.json_normalize(for_dataframe)
print(df)

表示結果(ちょっとなんのデータかはこれだけではわかりづらいですが、、)
無事データ取得できていました。

API経由で取得したデータの表示結果

TogglのAPIの詳細については以下のリファレンスを参照して下さい。


2.簡単に分析したい内容を作成(データを可視化しアプリで表示する内容を準備)

dataframeに入れて仕舞えばこっちのもので、あとはpandasやnampy、matplotを使って自分が見せたい形に、データを可視化してアプリで表示したい内容のコードを書いていきます。
とりあえず、タスクごとに工数を降順で表示させるみたいなコード適当に書きました。

# extracted_valueごとのnumbersの合計を計算
sum_values = df.groupby('taskID')['duration'].sum().sort_values(ascending=False).head(10)
print(sum_values)

st.title("タスクごとの工数確認")
# グラフの整形
fig, ax = plt.subplots()
sum_values.plot(kind='bar', ax=ax, color='gray')  # グレースケールカラーを使用
plt.xlabel('Extracted Value')
plt.ylabel('Total Numbers')
plt.title('Total Numbers by Extracted Value')

# X軸のラベルの位置を均等にする
ax.set_xticks(range(len(sum_values)))
ax.set_xticklabels(sum_values.index, rotation=45, ha='right')

#グラフを表示
plt.tight_layout()
plt.show()
st.pyplot(fig)

3.Streamlitに記述する(アプリ化)

さてここからは、アプリとして公開するため、フロントエンドも含めて構築していきます。
ですがめっちゃ簡単です。(こだわらなければ)
先ほどのコードの冒頭に以下2行を追加するだけ。
app.pyというファイル名のアプリとして書き込みます。

%%writefile app.py
# 以下を「app.py」に書き込み

細かい機能は色々と実装できるので、細かく設定したい場合は、
Streamlitでアプリに実装できるUIなどは以下の記事等をご参考ください。
GPTに質問するでも良いかもです。

アプリを起動

!streamlit run app.py &>/dev/null&  # 「&>/dev/null&」により、出力を非表示にしてバックグランドジョブとして実行

4.Ngrokでgoogle colabをサーバー化して、アプリを擬似デプロイ

ここからさらに起動したアプリをサーバー上にデプロイしていきます。

まずは、冒頭で取得したNgorkのトークンを設定しておいてください。

!ngrok authtoken "YOUR AUTHTOKEN"

ngrokのプロセスを終了した上で、新たにポートを指定して接続します。
接続の結果、urlを取得完了。

ngrok.kill()  # プロセスの修了
url = ngrok.connect(port="8501")  # 接続

*ngrokの無料プランでは同時に1つのプロセスしか動かせないので、エラーが発生した場合は「ランタイム」→「セッションの管理」で不要なGoogle Colabのセッションを修了しておく

URLのhttpの部分をhttpsに変換する関数を設定。

def convert_http_to_https(url):
    if url.startswith("http://"):
        url = url.replace("http://", "https://", 1)
    return url

変換したurlを表示し、リンク先でアプリが動作することを確認します。

print(convert_http_to_https(url))

Printで表示したURLにアクセスするとVisit Siteのボタンが表示される。こちらを再度開きアプリが動けば動作している。

URLを表示後

アプリとして、タスクごとの工数が、matplotで表示された状態で閲覧できるようになりました。

タスクごとの工数

最後に

こちらで簡単にデータ分析ツールがデプロイできました。
最終的には、ユーザーから、IDとパスワードを受け取って、Togglにアクセルした上で、それらをインタラクティブに操作できるアプリに仕上げました。
グラフで表示する値などをセレクターから受け取って、その内容だけをグラフ化するような内容にアップグレードすることができました。

最終的なコードの全体像もどうぞ。

%%writefile app.py
# 以下を「app.py」に書き込み
import streamlit as st
import numpy as np
import pandas as pd
import requests
from base64 import b64encode
import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib
import json

# ---------- データフレーム ----------
st.title("Toggle データセットの確認")

# ユーザーからIDとPASSを受け取る
user_id = st.text_input("IDを入力してください:")
user_pass = st.text_input("PASSを入力してください:", type="password")

if user_id and user_pass:
    credentials = f"{user_id}:{user_pass}".encode("ascii")
    authorization = b64encode(credentials).decode("ascii")
    headers = {'content-type': 'application/json', 'Authorization': f'Basic {authorization}'}

    data = requests.get('https://api.track.toggl.com/api/v9/me/time_entries', headers=headers)

    # 応答のステータスコードを表示
    st.write("Status Code:", data.status_code)

    # 応答が成功した場合のみJSONを表示
    if data.status_code == 200:
        st.dataframe(data.json())
    else:
        st.write("Error:", data.text)
else:
    st.write("IDとPASSを入力してください.")
# この修正により、リクエストが失敗した場合にはステータスコードとエラーメッセージを表示します。これによって問題の原因を特定しやすくなります。

print(data.json())
for_dataframe = data.json()
df = pd.json_normalize(for_dataframe)
# columns = df.columns.tolist()
# print(columns)

# target_columnからアンダースコアで区切られた2番目の値を抽出
def extract_second_part(x):
    parts = x.split('_')
    return parts[1] if len(parts) > 1 else x

df['taskID'] = df['description'].apply(extract_second_part)


# ---------- extracted_valueごとのnumbersの合計を計算 ----------

sum_values = df.groupby('taskID')['duration'].sum().sort_values(ascending=False).head(10)
print(sum_values)

st.title("タスクごとの工数確認")
# グラフに可視化
fig, ax = plt.subplots()
sum_values.plot(kind='bar', ax=ax, color='gray')  # グレースケールカラーを使用
plt.xlabel('Extracted Value')
plt.ylabel('Total Numbers')
plt.title('Total Numbers by Extracted Value')

# X軸のラベルの位置を均等にする
ax.set_xticks(range(len(sum_values)))
ax.set_xticklabels(sum_values.index, rotation=45, ha='right')

plt.tight_layout()
plt.show()
st.pyplot(fig)


# ----------  ----------

# タイムスタンプ型の 'at' カラムを日付型に変換
df['at_date'] = pd.to_datetime(df['at']).dt.date

# target_columnからアンダースコアで区切られた2番目の値を抽出
def extract_second_part(x):
    parts = x.split('_')
    return parts[1] if len(parts) > 1 else x

df['taskID'] = df['description'].apply(extract_second_part)

# Streamlitでマルチセレクトボックスを作成
selected_descriptions = st.multiselect(
    'Select taskID:',
    df['taskID'].unique()
)

# グラフのプロットの準備
fig, ax = plt.subplots()

# 選択されたdescriptionごとにグラフをプロット
for taskID in selected_descriptions:
    filtered_df = df[df['taskID'] == taskID]
    sum_durations_by_date = filtered_df.groupby('at_date')['duration'].sum()
    sum_durations_by_date.plot(kind='line', ax=ax, label=taskID)

plt.xlabel('Date')
plt.ylabel('Total Duration')
plt.title('Total Duration by Date')
plt.xticks(rotation=45)
plt.legend()
plt.tight_layout()

# Streamlitでのグラフ表示
st.pyplot(fig)
# このコードは、選択された各descriptionに対応するdurationの合計を、異なる色でライングラフにプロットします。X軸には日付、Y軸には合計時間が表示され、凡例も自動的に表示されます。

いかがでしたか?めっちゃ簡単にデータ分析のアプリが動きました。
大規模な開発のことまで明確にわかるわけではないかもですが、個人的にも自分で作りたいものを簡単に作ってみる入門的内容としてはすごく面白い題材でした。
これは実際の業務での分析と共有での活用の幅もかなり広がりそうだなと思いました。

(*詳しい方で説明おかしい部分があればぜひご指摘ください。)


この記事が気に入ったらサポートをしてみませんか?