前回は家計簿アプリの基本機能を作成しました。しかし、前回のままだとデータの一括削除しかできないので、今回は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ファイルとして保存します。