Streamlitで家計簿アプリを作ろう!その2

Python

前回は家計簿アプリの基本機能を作成しました。しかし、前回のままだとデータの一括削除しかできないので、今回は1行ずつ選択して削除できる機能を追加します。
ただし、Streamlitはデザインの自由度が低いため、もっと整ったレイアウトにするには他のフレームワーク(DjangoやFlask)を使うのが向いています。

アプリイメージ

削除する行の選択

削除のための表示はスペースを取るので、通常は一覧で表示し、削除モードにしたときだけ、削除する行を選択するための表示にします。

一覧表示

削除の実行

1行ずるデータが表示されるので、削除したい行を選択します。
削除選択
削除後はこのように削除された状態になります。
削除後

コード全体

import streamlit as st
import pandas as pd

# セッション状態を初期化
if 'data' not in st.session_state:
    st.session_state.data = pd.DataFrame(columns=["日付", "項目", "金額"])
    st.session_state.clear_data = False  # クリアフラグを初期化

if 'selected_rows' not in st.session_state:
    st.session_state.selected_rows = []
    st.session_state.delete_mode = False  # 削除モードを初期化

# Streamlitアプリケーションのタイトル
st.title("家計簿アプリ")

# 収支データの入力フォーム
st.header("収支の記録")
date = st.date_input("日付", pd.to_datetime("today"))
item = st.text_input("項目")
amount = st.number_input("金額", value=0, step=1)  # 金額を整数として入力

# データをデータフレームに追加
if st.button("記録する"):
    st.session_state.data = st.session_state.data.append({"日付": date, "項目": item, "金額": int(amount)}, ignore_index=True)

# データフレームの表示
st.header("収支データ")

# 削除モードのトグルボタン
st.session_state.delete_mode = st.checkbox("削除モード", value=st.session_state.delete_mode)  # キーを指定しない

if len(st.session_state.data) > 0:
    if st.session_state.delete_mode:
        st.write("収支データを選択してください:")
        for index, row in st.session_state.data.iterrows():
            selected = st.checkbox(label="", value=False, key=index)
            if selected:
                st.session_state.selected_rows.append(index)  # 選択された行のインデックスをセッション状態に追加
            st.write(st.session_state.data.loc[[index], ["日付", "項目", "金額"]])

        # 行を削除するボタン
        if st.button("選択した行を削除") and st.session_state.selected_rows:
            st.session_state.data.drop(st.session_state.selected_rows, inplace=True)
            st.session_state.selected_rows = []  # 選択された行をリセット
            st.success("選択した行を削除しました。")
            st.experimental_rerun()  # データを削除後に再表示

    else:
        # 通常モードの一覧表示
        st.write(st.session_state.data)

# 統計情報の表示
st.header("統計情報")
st.write("合計支出:", st.session_state.data[st.session_state.data["金額"] < 0]["金額"].sum())
st.write("合計収入:", st.session_state.data[st.session_state.data["金額"] > 0]["金額"].sum())

# アプリのクリアボタン
if st.button("データをクリア"):
    st.session_state.data = pd.DataFrame(columns=["日付", "項目", "金額"])
    st.session_state.selected_rows = []  # 選択状態もクリア
    st.session_state.delete_mode = False  # 削除モードもクリア
    st.session_state.clear_data = True  # クリアフラグをTrueに設定
    st.success("データがクリアされました.")

# データがクリアされた場合、初期画面を表示
if st.session_state.clear_data:
    st.session_state.clear_data = False
    st.experimental_rerun()  # データをクリア後に再表示

# データの保存
st.session_state.data.to_csv("家計簿データ.csv", index=False)

コード解説

削除モードのトグルボタン

st.session_state.delete_mode = st.checkbox("削除モード", value=st.session_state.delete_mode)  # キーを指定しない

この行は、Streamlitのウィジェットを使用して「削除モード」をトグルするためのチェックボックスを表示しています。st.session_state.delete_mode の値を変更して削除モードの有効/無効を切り替えます。

削除モードでのデータ表示

if st.session_state.delete_mode:
    st.write("収支データを選択してください:")
    for index, row in st.session_state.data.iterrows():
        selected = st.checkbox(label="", value=False, key=index)
        if selected:
            st.session_state.selected_rows.append(index)  # 選択された行のインデックスをセッション状態に追加
        st.write(st.session_state.data.loc[[index], ["日付", "項目", "金額"]])

この部分は、削除モードが有効な場合に実行されます。収支データの各行に対して、チェックボックスを表示し、ユーザーが行を選択できるようにします。選択された行のインデックスは st.session_state.selected_rows に追加されます。

行を削除するボタン

if st.button("選択した行を削除") and st.session_state.selected_rows:
    st.session_state.data.drop(st.session_state.selected_rows, inplace=True)
    st.session_state.selected_rows = []  # 選択された行をリセット
    st.success("選択した行を削除しました.")
    st.experimental_rerun()  # データを削除後に再表示

この部分は、「選択した行を削除」ボタンが押されたときに実行されます。選択された行のインデックスに基づいて、データフレームから行を削除します。削除後、成功メッセージが表示され、st.experimental_rerun() を使用してデータを削除後に再表示します。これにより、削除操作が反映された新しいデータが表示されます。

そのほかの部分の概要は以下です。

セッション状態の初期化

if 'data' not in st.session_state:
    st.session_state.data = pd.DataFrame(columns=["日付", "項目", "金額"])
    st.session_state.clear_data = False  # クリアフラグを初期化

if 'selected_rows' not in st.session_state:
    st.session_state.selected_rows = []
    st.session_state.delete_mode = False  # 削除モードを初期化

この部分では、Streamlitのセッション状態を初期化しています。セッション状態を使用することで、アプリケーション間でデータを保持できます。

収支データの入力フォーム

st.header("収支の記録")
date = st.date_input("日付", pd.to_datetime("today"))
item = st.text_input("項目")
amount = st.number_input("金額", value=0, step=1)  # 金額を整数として入力

この部分では、収支データを入力するためのフォームを表示しています。日付、項目、金額を入力できます。

データをデータフレームに追加

if st.button("記録する"):
    st.session_state.data = st.session_state.data.append({"日付": date, "項目": item, "金額": int(amount)}, ignore_index=True)

「記録する」ボタンが押されたときに、入力されたデータをデータフレームに追加しています。

データフレームの表示

st.header("収支データ")

ここでは、収支データを表示するセクションのヘッダーを設定しています。

統計情報の表示

st.header("統計情報")
st.write("合計支出:", st.session_state.data[st.session_state.data["金額"] < 0]["金額"].sum())
st.write("合計収入:", st.session_state.data[st.session_state.data["金額"] > 0]["金額"].sum())

収支データから統計情報(合計支出と合計収入)を表示しています。

アプリのクリアボタン

if st.button("データをクリア"):
    st.session_state.data = pd.DataFrame(columns=["日付", "項目", "金額"])
    st.session_state.selected_rows = []  # 選択状態もクリア
    st.session_state.delete_mode = False  # 削除モードもクリア
    st.session_state.clear_data = True  # クリアフラグをTrueに設定
    st.success("データがクリアされました.")

「データをクリア」ボタンが押されたときに、データをクリアし、セッション状態をリセットします。

データの保存

st.session_state.data.to_csv("家計簿データ.csv", index=False)

データをCSVファイルとして保存します。

GoogleColabのコード

タイトルとURLをコピーしました